diff options
author | Carl Hetherington <carl@carlh.net> | 2012-01-23 19:35:56 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2012-01-23 19:35:56 +0000 |
commit | 4c224ef9558b0d555cad533dfe276c8f6dbd7bde (patch) | |
tree | 92be487e4a34c066308af01fff219099235c5c34 | |
parent | 0bede516beebc906460933094e4722fcb68b5aa0 (diff) |
Speed up iterating over an entire PortSet by keeping a
separate list of all ports.
git-svn-id: svn://localhost/ardour2/branches/3.0@11318 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | libs/ardour/ardour/port_set.h | 8 | ||||
-rw-r--r-- | libs/ardour/port_set.cc | 53 |
2 files changed, 36 insertions, 25 deletions
diff --git a/libs/ardour/ardour/port_set.h b/libs/ardour/ardour/port_set.h index a6a0593946..690875cd86 100644 --- a/libs/ardour/ardour/port_set.h +++ b/libs/ardour/ardour/port_set.h @@ -34,6 +34,10 @@ class MidiPort; * This allows access to all the ports as a list, ignoring type, or accessing * the nth port of a given type. Note that port(n) and nth_audio_port(n) may * NOT return the same port. + * + * Each port is held twice; once in a per-type vector of vectors (_ports) + * and once in a vector of all port (_all_ports). This is to speed up the + * fairly common case of iterating over all ports. */ class PortSet : public boost::noncopyable { public: @@ -60,7 +64,7 @@ public: /** Remove all ports from the PortSet. Ports are not deregistered with * the engine, it's the caller's responsibility to not leak here! */ - void clear() { _ports.clear(); } + void clear(); const ChanCount& count() const { return _count; } @@ -132,6 +136,8 @@ private: // Vector of vectors, indexed by DataType::to_index() std::vector<PortVec> _ports; + // All ports in _ports in one vector, to speed some operations + PortVec _all_ports; ChanCount _count; }; diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 8ad8531f5d..7e9f0656c5 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -71,14 +71,27 @@ static bool sort_ports_by_name (boost::shared_ptr<Port> a, boost::shared_ptr<Por } } + +static bool sort_ports_by_type_and_name (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b) +{ + if (a->type() != b->type()) { + return a->type() < b->type(); + } + + return sort_ports_by_name (a, b); +} + void PortSet::add (boost::shared_ptr<Port> port) { PortVec& v = _ports[port->type()]; v.push_back(port); + _all_ports.push_back(port); sort(v.begin(), v.end(), sort_ports_by_name); + sort(_all_ports.begin(), _all_ports.end(), sort_ports_by_type_and_name); + _count.set(port->type(), _count.get(port->type()) + 1); assert(_count.get(port->type()) == _ports[port->type()].size()); } @@ -86,6 +99,11 @@ PortSet::add (boost::shared_ptr<Port> port) bool PortSet::remove (boost::shared_ptr<Port> port) { + PortVec::iterator i = find(_all_ports.begin(), _all_ports.end(), port); + if (i != _all_ports.end()) { + _all_ports.erase(i); + } + for (std::vector<PortVec>::iterator l = _ports.begin(); l != _ports.end(); ++l) { PortVec::iterator i = find(l->begin(), l->end(), port); if (i != l->end()) { @@ -103,40 +121,20 @@ PortSet::remove (boost::shared_ptr<Port> port) size_t PortSet::num_ports() const { - size_t ret = 0; - - for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) - ret += (*l).size(); - - return ret; + return _all_ports.size(); } bool PortSet::contains (boost::shared_ptr<const Port> port) const { - for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) - if (find (l->begin(), l->end(), port) != l->end()) - return true; - - return false; + return find(_all_ports.begin(), _all_ports.end(), port) != _all_ports.end(); } boost::shared_ptr<Port> PortSet::port(size_t n) const { - // This is awesome. Awesomely slow. - - size_t size_so_far = 0; - - for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) { - if (n < size_so_far + l->size()) { - return (*l)[n - size_so_far]; - } else { - size_so_far += l->size(); - } - } - - return boost::shared_ptr<Port> (); // n out of range + assert(n < _all_ports.size()); + return _all_ports[n]; } boost::shared_ptr<Port> @@ -163,4 +161,11 @@ PortSet::nth_midi_port(size_t n) const return boost::dynamic_pointer_cast<MidiPort> (port (DataType::MIDI, n)); } +void +PortSet::clear() +{ + _ports.clear(); + _all_ports.clear(); +} + } // namepace ARDOUR |