summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2020-04-07 10:18:16 -0600
committerPaul Davis <paul@linuxaudiosystems.com>2020-04-07 13:23:49 -0600
commitb9cb306e8b9a330ec5211ccdfde6b90f17701099 (patch)
tree4e3e2d90fe9d0747a06e08c8bfd099fc275c07b4 /libs/ardour/ardour
parent1eb98316a3467c94842f6b6ba21eaf4470760880 (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.h4
-rw-r--r--libs/ardour/ardour/port.h2
-rw-r--r--libs/ardour/ardour/port_engine.h26
-rw-r--r--libs/ardour/ardour/port_engine_shared.h69
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 ()) {