diff --git a/libs/ardour/ardour/port_engine_shared.h b/libs/ardour/ardour/port_engine_shared.h index e193da37c9..bf6be04bb0 100644 --- a/libs/ardour/ardour/port_engine_shared.h +++ b/libs/ardour/ardour/port_engine_shared.h @@ -104,10 +104,6 @@ class LIBARDOUR_API BackendPort : public ProtoPort void update_connected_latency (bool for_playback); - bool operator< (BackendPort const& rhs) const { - return PBD::naturally_less (name ().c_str (), rhs.name ().c_str ()); - } - protected: PortEngineSharedImpl& _backend; @@ -219,17 +215,20 @@ protected: struct SortByPortName { bool operator() (BackendPortHandle lhs, BackendPortHandle rhs) const { - return *lhs < *rhs; + return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ()); } }; - typedef std::map PortMap; // fast lookup in _ports - typedef std::set PortIndex; // fast lookup in _ports - SerializedRCUManager _portmap; - SerializedRCUManager _ports; + typedef std::map PortMap; // fast-lookup by name + typedef std::set PortIndex; // name-based + typedef std::set PortRegistry; // std::less<>, safe during rename + + SerializedRCUManager _portmap; + SerializedRCUManager _ports; + SerializedRCUManager _portregistry; bool valid_port (BackendPortHandle port) const { - boost::shared_ptr p = _ports.reader (); + boost::shared_ptr p = _portregistry.reader (); return p->find (port) != p->end (); } diff --git a/libs/ardour/port_engine_shared.cc b/libs/ardour/port_engine_shared.cc index 6a5cbff369..0aea69e340 100644 --- a/libs/ardour/port_engine_shared.cc +++ b/libs/ardour/port_engine_shared.cc @@ -270,6 +270,7 @@ PortEngineSharedImpl::PortEngineSharedImpl (PortManager& mgr, std::string const : _instance_name (str) , _portmap (new PortMap) , _ports (new PortIndex) + , _portregistry (new PortRegistry) { g_atomic_int_set (&_port_change_flag, 0); pthread_mutex_init (&_port_callback_mutex, 0); @@ -415,13 +416,16 @@ PortEngineSharedImpl::add_port (const std::string& name, ARDOUR::DataType type, } { - RCUWriter index_writer (_ports); - RCUWriter map_writer (_portmap); + RCUWriter index_writer (_ports); + RCUWriter map_writer (_portmap); + RCUWriter registry_writer (_portregistry); - boost::shared_ptr ps = index_writer.get_copy (); - boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr ps = index_writer.get_copy (); + boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr pr = registry_writer.get_copy (); ps->insert (port); + pr->insert (port); pm->insert (make_pair (name, port)); } @@ -434,11 +438,13 @@ PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle) BackendPortPtr port = boost::dynamic_pointer_cast(port_handle); { - RCUWriter index_writer (_ports); - RCUWriter map_writer (_portmap); + RCUWriter index_writer (_ports); + RCUWriter map_writer (_portmap); + RCUWriter registry_writer (_portregistry); - boost::shared_ptr ps = index_writer.get_copy (); - boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr ps = index_writer.get_copy (); + boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr pr = registry_writer.get_copy (); PortIndex::iterator i = std::find (ps->begin(), ps->end(), boost::dynamic_pointer_cast (port_handle)); @@ -451,10 +457,12 @@ PortEngineSharedImpl::unregister_port (PortEngine::PortHandle port_handle) pm->erase (port->name()); ps->erase (i); + pr->erase (*i); } _ports.flush (); _portmap.flush (); + _portregistry.flush (); } @@ -467,12 +475,13 @@ PortEngineSharedImpl::unregister_ports (bool system_only) _system_midi_out.clear(); { - RCUWriter index_writer (_ports); - RCUWriter map_writer (_portmap); - - boost::shared_ptr ps = index_writer.get_copy (); - boost::shared_ptr pm = map_writer.get_copy (); + RCUWriter index_writer (_ports); + RCUWriter map_writer (_portmap); + RCUWriter registry_writer (_portregistry); + boost::shared_ptr ps = index_writer.get_copy (); + boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr pr = registry_writer.get_copy (); for (PortIndex::iterator i = ps->begin (); i != ps->end ();) { PortIndex::iterator cur = i++; @@ -481,25 +490,29 @@ PortEngineSharedImpl::unregister_ports (bool system_only) port->disconnect_all (port); pm->erase (port->name()); ps->erase (cur); + pr->erase (port); } } } _ports.flush (); _portmap.flush (); + _portregistry.flush (); } void PortEngineSharedImpl::clear_ports () { { - RCUWriter index_writer (_ports); - RCUWriter map_writer (_portmap); + RCUWriter index_writer (_ports); + RCUWriter map_writer (_portmap); + RCUWriter registry_writer (_portregistry); - boost::shared_ptr ps = index_writer.get_copy(); - boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr ps = index_writer.get_copy (); + boost::shared_ptr pm = map_writer.get_copy (); + boost::shared_ptr pr = registry_writer.get_copy (); - if (ps->size () || pm->size ()) { + if (ps->size () || pm->size () || pr->size ()) { PBD::warning << _("PortEngineSharedImpl: recovering from unclean shutdown, port registry is not empty.") << endmsg; _system_inputs.clear(); _system_outputs.clear(); @@ -507,11 +520,13 @@ PortEngineSharedImpl::clear_ports () _system_midi_out.clear(); ps->clear(); pm->clear(); + pr->clear(); } } _ports.flush (); _portmap.flush (); + _portregistry.flush (); g_atomic_int_set (&_port_change_flag, 0); pthread_mutex_lock (&_port_callback_mutex); @@ -544,20 +559,20 @@ PortEngineSharedImpl::set_port_name (PortEngine::PortHandle port_handle, const s const std::string old_name = port->name(); /* PortIndex std::set is sorted by name, using the name as key. - * So name-changes need to update the set + * So name-changes need to update the set. + * PortRegistry does not change */ RCUWriter index_writer (_ports); + RCUWriter map_writer (_portmap); + boost::shared_ptr ps = index_writer.get_copy (); + boost::shared_ptr pm = map_writer.get_copy (); ps->erase (port); int ret = port->set_name (newname); ps->insert (port); if (ret == 0) { - - RCUWriter map_writer (_portmap); - boost::shared_ptr pm = map_writer.get_copy (); - pm->erase (old_name); pm->insert (make_pair (newname, port)); }