diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2020-04-07 10:18:16 -0600 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2020-04-07 13:23:49 -0600 |
commit | b9cb306e8b9a330ec5211ccdfde6b90f17701099 (patch) | |
tree | 4e3e2d90fe9d0747a06e08c8bfd099fc275c07b4 /libs/ardour/ardour | |
parent | 1eb98316a3467c94842f6b6ba21eaf4470760880 (diff) |
use shared_ptr to manage backend port lifetimes (Pulse,ALSA,Dummy,JACK)
JACK is not yet finished.
Changes also include minor reformatting and a spelling correction (latecies to latencies)
Diffstat (limited to 'libs/ardour/ardour')
-rw-r--r-- | libs/ardour/ardour/audioengine.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/port.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/port_engine.h | 26 | ||||
-rw-r--r-- | libs/ardour/ardour/port_engine_shared.h | 69 |
4 files changed, 59 insertions, 42 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 3d08759787..70006fcf87 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -284,8 +284,8 @@ class LIBARDOUR_API AudioEngine : public PortManager, public SessionHandlePtr MTDM* _mtdm; MIDIDM* _mididm; LatencyMeasurement _measuring_latency; - PortEngine::PortHandle _latency_input_port; - PortEngine::PortHandle _latency_output_port; + PortEngine::PortPtr _latency_input_port; + PortEngine::PortPtr _latency_output_port; samplecnt_t _latency_flush_samples; std::string _latency_input_name; std::string _latency_output_name; diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index aa19ca85ed..781c970e2a 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -159,7 +159,7 @@ protected: Port (std::string const &, DataType, PortFlags); - PortEngine::PortHandle _port_handle; + PortEngine::PortPtr _port_handle; static bool _connecting_blocked; static pframes_t _cycle_nframes; /* access only from process() tree */ diff --git a/libs/ardour/ardour/port_engine.h b/libs/ardour/ardour/port_engine.h index 483206578a..056b70f31b 100644 --- a/libs/ardour/ardour/port_engine.h +++ b/libs/ardour/ardour/port_engine.h @@ -75,6 +75,12 @@ class PortManager; * documentation, on which this entire object is based. */ +class LIBARDOUR_API ProtoPort { + public: + ProtoPort() {} + virtual ~ProtoPort () {} +}; + class LIBARDOUR_API PortEngine { public: @@ -88,14 +94,24 @@ public: /** Opaque handle to use as reference for Ports * - * We use void* here so that the API can be defined for any implementation. + * The handle needs to be lifetime managed (i.e. a shared_ptr type) + * in order to allow RCU to provide lock-free cross-thread operations + * on ports and ports containers. * * We could theoretically use a template (PortEngine\<T\>) and define * PortHandle as T, but this complicates the desired inheritance * pattern in which FooPortEngine handles things for the Foo API, * rather than being a derivative of PortEngine\<Foo\>. + * + * We use this to declare return values and members of structures. + */ + typedef boost::shared_ptr<ProtoPort> PortPtr; + + /* We use this to declare arguments to methods/functions, in order to + * avoid copying shared_ptr<ProtoPort> every time (a practice we use in + * other contexts where we pass shared_ptr<T>). */ - typedef void* PortHandle; + typedef PortPtr const & PortHandle; /** Return the name of this process as used by the port manager * when naming ports. @@ -164,7 +180,7 @@ public: * @param name Full port-name to lookup * @return PortHandle if lookup was successful, or an "empty" PortHandle (analogous to a null pointer) if no such port exists. */ - virtual PortHandle get_port_by_name (const std::string& name) const = 0; + virtual PortPtr get_port_by_name (const std::string& name) const = 0; /** Find the set of ports whose names, types and flags match * specified values, place the names of each port into \p ports . @@ -194,7 +210,7 @@ public: * @param flags flags of the port to create * @return a reference to the port, otherwise return a null pointer. */ - virtual PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0; + virtual PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0; /* Destroy the port referred to by \p port, including all resources * associated with it. This will also disconnect \p port from any ports it @@ -202,7 +218,7 @@ public: * * @param port \ref PortHandle of the port to destroy */ - virtual void unregister_port (PortHandle port) = 0; + virtual void unregister_port (PortHandle port) = 0; /* Connection management */ diff --git a/libs/ardour/ardour/port_engine_shared.h b/libs/ardour/ardour/port_engine_shared.h index 7997cb9e9d..bb95277346 100644 --- a/libs/ardour/ardour/port_engine_shared.h +++ b/libs/ardour/ardour/port_engine_shared.h @@ -39,25 +39,28 @@ namespace ARDOUR { class PortEngineSharedImpl; class PortManager; -class LIBARDOUR_API BackendPort +class BackendPort; + +typedef boost::shared_ptr<BackendPort> BackendPortPtr; +typedef boost::shared_ptr<BackendPort> const & BackendPortHandle; + +class LIBARDOUR_API BackendPort : public ProtoPort { -protected: + protected: BackendPort (PortEngineSharedImpl& b, const std::string&, PortFlags); -public: + public: virtual ~BackendPort (); const std::string& name () const { return _name; } const std::string& pretty_name () const { return _pretty_name; } - int set_name (const std::string& name) - { + int set_name (const std::string& name) { _name = name; return 0; } - int set_pretty_name (const std::string& name) - { + int set_pretty_name (const std::string& name) { _pretty_name = name; return 0; } @@ -71,17 +74,16 @@ public: bool is_terminal () const { return flags () & IsTerminal; } bool is_connected () const { return _connections.size () != 0; } - bool is_connected (const BackendPort* port) const; + bool is_connected (BackendPortHandle port) const; bool is_physically_connected () const; - const std::set<BackendPort*>& get_connections () const - { + const std::set<BackendPortPtr>& get_connections () const { return _connections; } - int connect (BackendPort* port); - int disconnect (BackendPort* port); - void disconnect_all (); + int connect (BackendPortHandle port, BackendPortHandle self); + int disconnect (BackendPortHandle port, BackendPortHandle self); + void disconnect_all (BackendPortHandle self); virtual void* get_buffer (pframes_t nframes) = 0; @@ -103,10 +105,10 @@ private: const PortFlags _flags; LatencyRange _capture_latency_range; LatencyRange _playback_latency_range; - std::set<BackendPort*> _connections; + std::set<BackendPortPtr> _connections; - void _connect (BackendPort*, bool); - void _disconnect (BackendPort*, bool); + void store_connection (BackendPortHandle); + void remove_connection (BackendPortHandle); }; // class BackendPort @@ -129,7 +131,7 @@ public: int set_port_name (PortEngine::PortHandle, const std::string&); std::string get_port_name (PortEngine::PortHandle) const; PortFlags get_port_flags (PortEngine::PortHandle) const; - PortEngine::PortHandle get_port_by_name (const std::string&) const; + PortEngine::PortPtr get_port_by_name (const std::string&) const; int get_port_property (PortEngine::PortHandle, const std::string& key, std::string& value, std::string& type) const; int set_port_property (PortEngine::PortHandle, const std::string& key, const std::string& value, const std::string& type); @@ -138,8 +140,8 @@ public: DataType port_data_type (PortEngine::PortHandle) const; - PortEngine::PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); - virtual void unregister_port (PortEngine::PortHandle); + PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); + virtual void unregister_port (PortEngine::PortHandle); int connect (const std::string& src, const std::string& dst); int disconnect (const std::string& src, const std::string& dst); @@ -158,36 +160,35 @@ public: protected: std::string _instance_name; - std::vector<BackendPort*> _system_inputs; - std::vector<BackendPort*> _system_outputs; - std::vector<BackendPort*> _system_midi_in; - std::vector<BackendPort*> _system_midi_out; + std::vector<BackendPortPtr> _system_inputs; + std::vector<BackendPortPtr> _system_outputs; + std::vector<BackendPortPtr> _system_midi_in; + std::vector<BackendPortPtr> _system_midi_out; + + virtual void update_system_port_latencies (); void clear_ports (); - PortEngine::PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); - void unregister_ports (bool system_only = false); + BackendPortPtr add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); + void unregister_ports (bool system_only = false); struct SortByPortName { - bool operator() (const BackendPort* lhs, const BackendPort* rhs) const - { + bool operator() (BackendPortHandle lhs, BackendPortHandle rhs) const { return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ()); } }; - typedef std::map<std::string, BackendPort*> PortMap; // fast lookup in _ports - typedef std::set<BackendPort*, SortByPortName> PortIndex; // fast lookup in _ports + typedef std::map<std::string, BackendPortPtr> PortMap; // fast lookup in _ports + typedef std::set<BackendPortPtr, SortByPortName> PortIndex; // fast lookup in _ports SerializedRCUManager<PortMap> _portmap; SerializedRCUManager<PortIndex> _ports; - bool valid_port (PortEngine::PortHandle port) const - { + bool valid_port (BackendPortHandle port) const { boost::shared_ptr<PortIndex> p = _ports.reader (); - return std::find (p->begin (), p->end (), static_cast<BackendPort*> (port)) != p->end (); + return std::find (p->begin (), p->end (), port) != p->end (); } - BackendPort* find_port (const std::string& port_name) const - { + BackendPortPtr find_port (const std::string& port_name) const { boost::shared_ptr<PortMap> p = _portmap.reader (); PortMap::const_iterator it = p->find (port_name); if (it == p->end ()) { |