From 37969d837e16c8fbac0821074495b5ebc2297d94 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 14 May 2012 17:07:53 +0000 Subject: [PATCH] remove virtual inheritance of sigc::trackable by Receiver and AbstractUI, done by changing Gtkmm2ext::UI to use composition (HAS-A) rather than inheritance (IS-A) for Receiver; use correct synchronization when starting up a BseUI event loop thread so that tests that start/stop quickly do not encounter a race condition git-svn-id: svn://localhost/ardour2/branches/3.0@12264 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/midi_ui.cc | 2 +- libs/gtkmm2ext/gtk_ui.cc | 12 +++++++----- libs/gtkmm2ext/gtkmm2ext/gtk_ui.h | 16 +++++++++++++++- libs/pbd/base_ui.cc | 15 +++++++++++++++ libs/pbd/pbd/base_ui.h | 10 +++++++++- libs/pbd/pbd/receiver.h | 2 +- libs/pbd/wscript | 1 + .../control_protocol/control_protocol.h | 3 ++- 8 files changed, 51 insertions(+), 10 deletions(-) diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc index 770a371457..78da32e427 100644 --- a/libs/ardour/midi_ui.cc +++ b/libs/ardour/midi_ui.cc @@ -45,7 +45,7 @@ MidiControlUI* MidiControlUI::_instance = 0; #include "pbd/abstract_ui.cc" /* instantiate the template */ MidiControlUI::MidiControlUI (Session& s) - : AbstractUI (_("midiui")) + : AbstractUI (X_("midiui")) , _session (s) { MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this)); diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index 3ec752af02..11b06b78ff 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -64,6 +64,8 @@ BaseUI::RequestType Gtkmm2ext::AddTimeout = BaseUI::new_request_type(); UI::UI (string namestr, int *argc, char ***argv) : AbstractUI (namestr) + , _receiver (*this) + { theMain = new Main (argc, argv); @@ -252,10 +254,10 @@ UI::load_rcfile (string path, bool themechange) void UI::run (Receiver &old_receiver) { - listen_to (error); - listen_to (info); - listen_to (warning); - listen_to (fatal); + _receiver.listen_to (error); + _receiver.listen_to (info); + _receiver.listen_to (warning); + _receiver.listen_to (fatal); /* stop the old receiver (text/console) once we hit the first idle */ @@ -266,7 +268,7 @@ UI::run (Receiver &old_receiver) theMain->run (); _active = false; stopping (); - hangup (); + _receiver.hangup (); return; } diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h index bba3fb6fdf..4bf82fb1aa 100644 --- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h +++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h @@ -88,8 +88,21 @@ struct UIRequest : public BaseUI::BaseRequestObject { } }; -class UI : public Receiver, public AbstractUI +class UI : public AbstractUI { + private: + class MyReceiver : public Receiver { + public: + MyReceiver (UI& ui) : _ui (ui) {} + void receive (Transmitter::Channel chn, const char *msg) { + _ui.receive (chn, msg); + } + private: + UI& _ui; + }; + + MyReceiver _receiver; + public: UI (std::string name, int *argc, char **argv[]); virtual ~UI (); @@ -183,6 +196,7 @@ class UI : public Receiver, public AbstractUI bool color_picked; void do_request (UIRequest*); + }; } /* namespace */ diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 31f956f4cf..c246a50656 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -74,11 +74,22 @@ void BaseUI::main_thread () { DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_self())); + std::cerr << string_compose ("%1: event loop running in thread %2\n", name(), pthread_self()); set_event_loop_for_thread (this); thread_init (); + _main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running)); _main_loop->run (); } +bool +BaseUI::signal_running () +{ + Glib::Mutex::Lock lm (_run_lock); + _running.signal (); + + return false; // don't call it again +} + void BaseUI::run () { @@ -91,7 +102,11 @@ BaseUI::run () /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ request_channel.drop_ios (); + Glib::Mutex::Lock lm (_run_lock); run_loop_thread = Thread::create (mem_fun (*this, &BaseUI::main_thread), true); + std::cerr << "wait for " << name() << " thread to start\n"; + _running.wait (_run_lock); + std::cerr << "\tthread now running\n"; } void diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index 414c9970d9..65a9f27b49 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -41,7 +41,7 @@ */ -class BaseUI : virtual public sigc::trackable, public PBD::EventLoop +class BaseUI : public sigc::trackable, public PBD::EventLoop { public: BaseUI (const std::string& name); @@ -76,6 +76,14 @@ class BaseUI : virtual public sigc::trackable, public PBD::EventLoop Glib::RefPtr _main_loop; Glib::Thread* run_loop_thread; + Glib::Mutex _run_lock; + Glib::Cond _running; + + /* this signals _running from within the event loop, + from an idle callback + */ + + bool signal_running (); /** Derived UI objects can implement thread_init() * which will be called by the event loop thread diff --git a/libs/pbd/pbd/receiver.h b/libs/pbd/pbd/receiver.h index 5e32c7d67f..32fb84fa38 100644 --- a/libs/pbd/pbd/receiver.h +++ b/libs/pbd/pbd/receiver.h @@ -28,7 +28,7 @@ class strstream; -class Receiver : virtual public sigc::trackable +class Receiver : public sigc::trackable { public: Receiver (); diff --git a/libs/pbd/wscript b/libs/pbd/wscript index 069936b28f..60799f0116 100644 --- a/libs/pbd/wscript +++ b/libs/pbd/wscript @@ -142,6 +142,7 @@ def build(bld): testobj.includes = obj.includes + ['test', '../pbd'] testobj.uselib = 'CPPUNIT XML SNDFILE' testobj.use = 'libpbd' + testobj.name = 'libpbd-tests' if sys.platform != 'darwin': testobj.linkflags = ['-lrt'] diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 6021f189fe..155c9236da 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -39,7 +39,8 @@ class Route; class Session; class Bundle; -class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList, public BasicUI { +class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList, public BasicUI +{ public: ControlProtocol (Session&, std::string name); virtual ~ControlProtocol();