Fix crashes on x-thread signal emission.
[dcpomatic.git] / src / lib / ui_signaller.h
index 428ab698f1d3028f05c42705bb1ad76787120ba1..9d4495cd18921822b2fcfa02836a3c916f2cfedd 100644 (file)
 #include <boost/asio.hpp>
 #include <boost/thread.hpp>
 
+class Signaller;
+
 /** A class to allow signals to be emitted from non-UI threads and handled
  *  by a UI thread.
  */
-class UISignaller
+class UISignaller : public boost::noncopyable
 {
 public:
        /** Create a UISignaller.  Must be called from the UI thread */
@@ -37,6 +39,25 @@ public:
                _ui_thread = boost::this_thread::get_id ();
        }
 
+       /* Do something next time the UI is idle */
+       template <typename T>
+       void when_idle (T f) {
+               _service.post (f);
+       }
+
+       /** Call this in the UI when it is idle */
+       size_t ui_idle () {
+               /* This executes any functors that have been post()ed to _service */
+               return _service.poll ();
+       }
+
+       /** 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:
        /** Emit a signal from any thread whose handlers will be called in the UI
         *  thread.  Use something like:
         *
@@ -54,15 +75,8 @@ public:
                }
        }
 
-       /** 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:
+       friend class Signaller;
+       
        /** 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 */