diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2015-12-28 10:14:17 -0500 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2015-12-28 10:14:17 -0500 |
commit | 0d9efc11484c901795ff4e9549a1a39715d0474d (patch) | |
tree | 956ab3cd570670bcb1ff68856553f5aec4a8e470 /libs/surfaces | |
parent | db4834027858b10f313c822c7fb3fad1617f11aa (diff) |
redesign cross-thread registration/signalling system
This new design will work even when threads that need to receive
messages from RT threads are created *after* the RT threads. The
existing design would fail because the RT thread(s) would never
be known the later created threads, and so signals emitted by the
RT thread and causing call_slot() in the receiver would end up
being enqueued using a lock-protected list. The new design ensures
that communication always uses a lock-free FIFO instead
Diffstat (limited to 'libs/surfaces')
-rw-r--r-- | libs/surfaces/control_protocol/control_protocol/control_protocol.h | 28 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport.cc | 19 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport.h | 3 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport_interface.cc | 9 | ||||
-rw-r--r-- | libs/surfaces/mackie/interface.cc | 10 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.cc | 19 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.h | 1 | ||||
-rw-r--r-- | libs/surfaces/osc/interface.cc | 9 | ||||
-rw-r--r-- | libs/surfaces/osc/osc.cc | 19 | ||||
-rw-r--r-- | libs/surfaces/osc/osc.h | 2 | ||||
-rw-r--r-- | libs/surfaces/wiimote/wiimote.cc | 2 |
11 files changed, 93 insertions, 28 deletions
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 8edb3f39a7..71e875419a 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -154,16 +154,24 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope extern "C" { class ControlProtocolDescriptor { public: - const char* name; /* descriptive */ - const char* id; /* unique and version-specific */ - void* ptr; /* protocol can store a value here */ - void* module; /* not for public access */ - int mandatory; /* if non-zero, always load and do not make optional */ - bool supports_feedback; /* if true, protocol has toggleable feedback mechanism */ - bool (*probe)(ControlProtocolDescriptor*); - ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*); - void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*); - + const char* name; /* descriptive */ + const char* id; /* unique and version-specific */ + void* ptr; /* protocol can store a value here */ + void* module; /* not for public access */ + int mandatory; /* if non-zero, always load and do not make optional */ + bool supports_feedback; /* if true, protocol has toggleable feedback mechanism */ + bool (*probe)(ControlProtocolDescriptor*); + ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*); + void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*); + /* this is required if the control protocol connects to signals + from libardour. they all do. It should allocate a + type-specific request buffer for the calling thread, and + store it in a thread-local location that will be used to + find it when sending the event loop a message + (e.g. call_slot()). It should also return the allocated + buffer as a void*. + */ + void* (*request_buffer_factory)(uint32_t); }; } diff --git a/libs/surfaces/faderport/faderport.cc b/libs/surfaces/faderport/faderport.cc index 135943d34f..f10f70dce5 100644 --- a/libs/surfaces/faderport/faderport.cc +++ b/libs/surfaces/faderport/faderport.cc @@ -66,7 +66,7 @@ using namespace std; FaderPort::FaderPort (Session& s) : ControlProtocol (s, _("Faderport")) - , AbstractUI<FaderPortRequest> ("faderport") + , AbstractUI<FaderPortRequest> (name()) , gui (0) , connection_state (ConnectionState (0)) , _device_active (false) @@ -210,6 +210,17 @@ FaderPort::~FaderPort () tear_down_gui (); } +void* +FaderPort::request_factory (uint32_t num_requests) +{ + /* AbstractUI<T>::request_buffer_factory() is a template method only + instantiated in this source module. To provide something visible for + use in the interface/descriptor, we have this static method that is + template-free. + */ + return request_buffer_factory (num_requests); +} + void FaderPort::start_midi_handling () { @@ -267,10 +278,10 @@ FaderPort::thread_init () { struct sched_param rtparam; - pthread_set_name (X_("FaderPort")); + pthread_set_name (event_loop_name().c_str()); - PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("FaderPort"), 2048); - ARDOUR::SessionEvent::create_per_thread_pool (X_("FaderPort"), 128); + PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048); + ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128); memset (&rtparam, 0, sizeof (rtparam)); rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */ diff --git a/libs/surfaces/faderport/faderport.h b/libs/surfaces/faderport/faderport.h index 6643e22369..025cf09e00 100644 --- a/libs/surfaces/faderport/faderport.h +++ b/libs/surfaces/faderport/faderport.h @@ -85,6 +85,7 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortReq there's no way to know if the device exists or not. */ static bool probe() { return true; } + static void* request_factory (uint32_t); XMLNode& get_state (); int set_state (const XMLNode&, int version); @@ -160,7 +161,7 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortReq std::string get_action (ButtonID, bool on_press, FaderPort::ButtonState = ButtonState (0)); std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles (); - + private: boost::shared_ptr<ARDOUR::Route> _current_route; boost::weak_ptr<ARDOUR::Route> pre_master_route; diff --git a/libs/surfaces/faderport/faderport_interface.cc b/libs/surfaces/faderport/faderport_interface.cc index dcfebff190..e7ea5af396 100644 --- a/libs/surfaces/faderport/faderport_interface.cc +++ b/libs/surfaces/faderport/faderport_interface.cc @@ -56,6 +56,12 @@ probe_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/) return FaderPort::probe (); } +static void* +faderport_request_buffer_factory (uint32_t num_requests) +{ + return FaderPort::request_factory (num_requests); +} + static ControlProtocolDescriptor faderport_midi_descriptor = { /*name : */ "Faderport", /*id : */ "uri://ardour.org/surfaces/faderport:0", @@ -65,7 +71,8 @@ static ControlProtocolDescriptor faderport_midi_descriptor = { /*supports_feedback : */ true, /*probe : */ probe_faderport_midi_protocol, /*initialize : */ new_faderport_midi_protocol, - /*destroy : */ delete_faderport_midi_protocol + /*destroy : */ delete_faderport_midi_protocol, + /*request_buffer_factory */ faderport_request_buffer_factory }; extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &faderport_midi_descriptor; } diff --git a/libs/surfaces/mackie/interface.cc b/libs/surfaces/mackie/interface.cc index 1a9760bcbe..3b04770660 100644 --- a/libs/surfaces/mackie/interface.cc +++ b/libs/surfaces/mackie/interface.cc @@ -74,6 +74,12 @@ probe_mackie_protocol (ControlProtocolDescriptor*) return MackieControlProtocol::probe(); } +static void* +mackie_request_buffer_factory (uint32_t num_requests) +{ + return MackieControlProtocol::request_factory (num_requests); +} + // Field names commented out by JE - 06-01-2010 static ControlProtocolDescriptor mackie_descriptor = { /*name : */ "Mackie", @@ -88,8 +94,8 @@ static ControlProtocolDescriptor mackie_descriptor = { /*supports_feedback : */ false, /*probe : */ probe_mackie_protocol, /*initialize : */ new_mackie_protocol, - /*destroy : */ delete_mackie_protocol + /*destroy : */ delete_mackie_protocol, + /*request_buffer_factory */ mackie_request_buffer_factory }; - extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &mackie_descriptor; } diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index dfd3fe6334..ea5e43d2ba 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -105,7 +105,7 @@ bool MackieControlProtocol::probe() MackieControlProtocol::MackieControlProtocol (Session& session) : ControlProtocol (session, X_("Mackie")) - , AbstractUI<MackieControlUIRequest> ("mackie") + , AbstractUI<MackieControlUIRequest> (name()) , _current_initial_bank (0) , _frame_last (0) , _timecode_type (ARDOUR::AnyTime::BBT) @@ -183,10 +183,10 @@ MackieControlProtocol::thread_init () { struct sched_param rtparam; - pthread_set_name (X_("MackieControl")); + pthread_set_name (event_loop_name().c_str()); - PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048); - ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128); + PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048); + ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128); memset (&rtparam, 0, sizeof (rtparam)); rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */ @@ -2251,3 +2251,14 @@ MackieControlProtocol::global_index (Strip& strip) return global; } + +void* +MackieControlProtocol::request_factory (uint32_t num_requests) +{ + /* AbstractUI<T>::request_buffer_factory() is a template method only + instantiated in this source module. To provide something visible for + use in the interface/descriptor, we have this static method that is + template-free. + */ + return request_buffer_factory (num_requests); +} diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index a1cee8ec7f..802d5a6235 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -178,6 +178,7 @@ class MackieControlProtocol */ static bool probe(); + static void* request_factory (uint32_t); mutable Glib::Threads::Mutex surfaces_lock; typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces; diff --git a/libs/surfaces/osc/interface.cc b/libs/surfaces/osc/interface.cc index d26a31788e..35b313945d 100644 --- a/libs/surfaces/osc/interface.cc +++ b/libs/surfaces/osc/interface.cc @@ -46,6 +46,12 @@ probe_osc_protocol (ControlProtocolDescriptor* /*descriptor*/) return true; // we can always do OSC } +static void* +osc_request_buffer_factory (uint32_t num_requests) +{ + return OSC::request_factory (num_requests); +} + static ControlProtocolDescriptor osc_descriptor = { /*name : */ "Open Sound Control (OSC)", /*id : */ "uri://ardour.org/surfaces/osc:0", @@ -55,7 +61,8 @@ static ControlProtocolDescriptor osc_descriptor = { /*supports_feedback : */ true, /*probe : */ probe_osc_protocol, /*initialize : */ new_osc_protocol, - /*destroy : */ delete_osc_protocol + /*destroy : */ delete_osc_protocol, + /*request_buffer_factory */ osc_request_buffer_factory }; extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &osc_descriptor; } diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 13261feffa..49c8bcc57c 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -73,7 +73,7 @@ static void error_callback(int, const char *, const char *) OSC::OSC (Session& s, uint32_t port) : ControlProtocol (s, X_("Open Sound Control (OSC)")) - , AbstractUI<OSCUIRequest> ("osc") + , AbstractUI<OSCUIRequest> (name()) , local_server (0) , remote_server (0) , _port(port) @@ -96,6 +96,17 @@ OSC::~OSC() _instance = 0; } +void* +OSC::request_factory (uint32_t num_requests) +{ + /* AbstractUI<T>::request_buffer_factory() is a template method only + instantiated in this source module. To provide something visible for + use in the interface/descriptor, we have this static method that is + template-free. + */ + return request_buffer_factory (num_requests); +} + void OSC::do_request (OSCUIRequest* req) { @@ -226,7 +237,7 @@ OSC::start () void OSC::thread_init () { - pthread_set_name (X_("OSC")); + pthread_set_name (event_loop_name().c_str()); if (_osc_unix_server) { Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR); @@ -244,8 +255,8 @@ OSC::thread_init () g_source_ref (remote_server); } - PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048); - SessionEvent::create_per_thread_pool (X_("OSC"), 128); + PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048); + SessionEvent::create_per_thread_pool (event_loop_name(), 128); } int diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h index 7c24869a00..3718d25525 100644 --- a/libs/surfaces/osc/osc.h +++ b/libs/surfaces/osc/osc.h @@ -79,6 +79,8 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest> int start (); int stop (); + static void* request_factory (uint32_t); + protected: void thread_init (); void do_request (OSCUIRequest*); diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc index aa36cdf300..db5fb55c2a 100644 --- a/libs/surfaces/wiimote/wiimote.cc +++ b/libs/surfaces/wiimote/wiimote.cc @@ -164,7 +164,7 @@ WiimoteControlProtocol::thread_init () pthread_set_name (X_("wiimote")); // allow to make requests to the GUI and RT thread(s) - PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self (), X_("wiimote"), 2048); + PBD::notify_event_loops_about_thread_creation (pthread_self (), X_("wiimote"), 2048); BasicUI::register_thread ("wiimote"); // connect a Wiimote |