X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fui_signaller.h;h=221bcbe9581ad2cdfaacdcaaeabf4487ab6e6723;hb=784c560e3437136d6006f8df2fb35f41585b6a8d;hp=0797d911e7123198f02f4c0fd3c061ae4dc3d9b4;hpb=63ea6b6c5ee64f8ee067c2b488d004b6dfe363e0;p=dcpomatic.git diff --git a/src/lib/ui_signaller.h b/src/lib/ui_signaller.h index 0797d911e..221bcbe95 100644 --- a/src/lib/ui_signaller.h +++ b/src/lib/ui_signaller.h @@ -22,28 +22,53 @@ #include #include +#include +/** A class to allow signals to be emitted from non-UI threads and handled + * by a UI thread. + */ class UISignaller { 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 (); + } } + /** Call this in the UI when it is idle */ void ui_idle () { _service.poll (); } + /** This should wake the UI and make it call ui_idle() */ virtual void wake_ui () = 0; 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;