From 4adb2f97cc991341d7e3b2a165e72373221a1b5e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 11 Jul 2013 12:56:35 -0400 Subject: Use timeout source to process ui requests on windows Using a timeout source to process ui events/requests is suboptimal but it works for the moment. Have to use g_source functions as glibmm functions are not thread safe AFAIK. Behaviour should be exactly the same on unix. --- libs/gtkmm2ext/gtk_ui.cc | 2 +- libs/pbd/base_ui.cc | 58 +++++++++++++++++++++++++++++++++++++++++------- libs/pbd/pbd/base_ui.h | 14 +++++++++--- 3 files changed, 62 insertions(+), 12 deletions(-) (limited to 'libs') diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index ee5e0c07f6..831fa7e38f 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -94,7 +94,7 @@ UI::UI (string namestr, int *argc, char ***argv) /* attach our request source to the default main context */ - attach_request_source (MainContext::get_default()); + attach_request_source (); errors = new TextViewer (800,600); errors->text().set_editable (false); diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 35ea6078ee..5725d69182 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -33,6 +33,8 @@ #include "i18n.h" +#include "pbd/debug.h" + using namespace std; using namespace PBD; using namespace Glib; @@ -42,13 +44,18 @@ BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type(); BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type(); BaseUI::BaseUI (const string& str) - : run_loop_thread (0) + : m_context(MainContext::get_default()) + , run_loop_thread (0) , _name (str) +#ifndef WIN32 , request_channel (true) +#endif { base_ui_instance = this; +#ifndef WIN32 request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler)); +#endif /* derived class must set _ok */ } @@ -95,11 +102,9 @@ BaseUI::run () /* to be called by UI's that need/want their own distinct, self-created event loop thread. */ - _main_loop = MainLoop::create (MainContext::create()); - request_channel.ios()->attach (_main_loop->get_context()); - - /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ - request_channel.drop_ios (); + m_context = MainContext::create(); + _main_loop = MainLoop::create (m_context); + attach_request_source (); Glib::Threads::Mutex::Lock lm (_run_lock); run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread)); @@ -115,6 +120,24 @@ BaseUI::quit () } } +#ifdef WIN32 +gboolean +BaseUI::_request_handler (gpointer data) +{ + BaseUI* ui = static_cast(data); + return ui->request_handler (); +} + +bool +BaseUI::request_handler () +{ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); + handle_ui_requests (); + // keep calling indefinitely at the timeout interval + return true; +} + +#else bool BaseUI::request_handler (Glib::IOCondition ioc) { @@ -133,20 +156,39 @@ BaseUI::request_handler (Glib::IOCondition ioc) /* handle requests */ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); handle_ui_requests (); } return true; } +#endif void BaseUI::signal_new_request () { + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n"); +#ifdef WIN32 + // handled in timeout, how to signal...? +#else request_channel.wakeup (); +#endif } +/** + * This method relies on the caller having already set m_context + */ void -BaseUI::attach_request_source (Glib::RefPtr context) +BaseUI::attach_request_source () { - request_channel.ios()->attach (context); + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n"); +#ifdef WIN32 + GSource* request_source = g_timeout_source_new(200); + g_source_set_callback (request_source, &BaseUI::_request_handler, this, NULL); + g_source_attach (request_source, m_context->gobj()); +#else + request_channel.ios()->attach (m_context); + /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ + request_channel.drop_ios (); +#endif } diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index 22784c9bfc..686af485e6 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -74,9 +74,10 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop bool _ok; Glib::RefPtr _main_loop; - Glib::Threads::Thread* run_loop_thread; + Glib::RefPtr m_context; + Glib::Threads::Thread* run_loop_thread; Glib::Threads::Mutex _run_lock; - Glib::Threads::Cond _running; + Glib::Threads::Cond _running; /* this signals _running from within the event loop, from an idle callback @@ -91,12 +92,17 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop virtual void thread_init () {}; +#ifdef WIN32 + static gboolean _request_handler (gpointer); + bool request_handler (); +#else /** Called when there input ready on the request_channel */ bool request_handler (Glib::IOCondition); +#endif void signal_new_request (); - void attach_request_source (Glib::RefPtr context); + void attach_request_source (); /** Derived UI objects must implement this method, * which will be called whenever there are requests @@ -108,7 +114,9 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop std::string _name; BaseUI* base_ui_instance; +#ifndef WIN32 CrossThreadChannel request_channel; +#endif static uint64_t rt_bit; -- cgit v1.2.3