X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fui_signaller.h;h=1d62547f61f79f5019f506b3a5b81712bc49167b;hb=e55d6da8817488f7a639130be54bcab152d19b89;hp=0797d911e7123198f02f4c0fd3c061ae4dc3d9b4;hpb=63ea6b6c5ee64f8ee067c2b488d004b6dfe363e0;p=dcpomatic.git diff --git a/src/lib/ui_signaller.h b/src/lib/ui_signaller.h index 0797d911e..1d62547f6 100644 --- a/src/lib/ui_signaller.h +++ b/src/lib/ui_signaller.h @@ -17,33 +17,61 @@ */ -#ifndef DVDOMATIC_UI_SIGNALLER_H -#define DVDOMATIC_UI_SIGNALLER_H +#ifndef DCPOMATIC_UI_SIGNALLER_H +#define DCPOMATIC_UI_SIGNALLER_H #include #include +#include -class UISignaller +/** A class to allow signals to be emitted from non-UI threads and handled + * by a UI thread. + */ +class UISignaller : public boost::noncopyable { public: + /** Create a UISignaller. Must be called from the UI thread */ UISignaller () : _work (_service) - {} - + { + _ui_thread = boost::this_thread::get_id (); + } + + /** Emit a signal from any thread whose handlers will be called in the UI + * thread. Use something like: + * + * ui_signaller->emit (boost::bind (boost::ref (SomeSignal), parameter)); + */ template void emit (T f) { - _service.post (f); + if (boost::this_thread::get_id() == _ui_thread) { + /* already in the UI thread */ + f (); + } else { + /* non-UI thread; post to the service and wake up the UI */ + _service.post (f); + wake_ui (); + } } - void ui_idle () { - _service.poll (); + /** Call this in the UI when it is idle */ + size_t ui_idle () { + return _service.poll (); } - virtual void wake_ui () = 0; + /** This should wake the UI and make it call ui_idle() */ + virtual void wake_ui () { + /* This is only a sensible implementation when there is no GUI... */ + ui_idle (); + } private: + /** A io_service which is used as the conduit for messages */ boost::asio::io_service _service; + /** Object required to keep io_service from stopping when it has nothing to do */ boost::asio::io_service::work _work; + /** The UI thread's ID */ + boost::thread::id _ui_thread; }; extern UISignaller* ui_signaller;