From d5e14b3d9144400fb8026fb9783a5a8582c0ad87 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 24 Apr 2012 16:45:38 +0000 Subject: eventloop and abstractui debugging, lots more commenting on abstractui/eventloop implementation; minor tweaks elsewhere git-svn-id: svn://localhost/ardour2/branches/3.0@12076 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/pbd/pbd/crossthread.h | 54 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) (limited to 'libs/pbd/pbd/crossthread.h') diff --git a/libs/pbd/pbd/crossthread.h b/libs/pbd/pbd/crossthread.h index a791be5798..13ab37d38d 100644 --- a/libs/pbd/pbd/crossthread.h +++ b/libs/pbd/pbd/crossthread.h @@ -26,20 +26,60 @@ #include +/** A simple abstraction of a mechanism of signalling one thread from another. + * The signaller calls ::wakeup() to tell the signalled thread to check for + * work to be done. + * + * This implementation provides both ::selectable() for use in direct + * poll/select-based event loops, and a Glib::IOSource via ::ios() for use + * in Glib main loop based situations. + */ + class CrossThreadChannel { public: - CrossThreadChannel(bool); + /** if @a non_blocking is true, the channel will not cause blocking + * when used in an event loop based on poll/select or the glib main + * loop. + */ + CrossThreadChannel(bool non_blocking); ~CrossThreadChannel(); + /** Tell the listening thread that is has work to do. + */ void wakeup(); - int selectable() const { return fds[0]; } - + + /* if the listening thread cares about the precise message + * it is being sent, then ::deliver() can be used to send + * a single byte message rather than a simple wakeup. These + * two mechanisms should not be used on the same CrossThreadChannel + * because there is no way to know which byte value will be used + * for ::wakeup() + */ int deliver (char msg); + + /** if using ::deliver() to wakeup the listening thread, then + * the listener should call ::receive() to fetch the message + * type from the channel. + */ int receive (char& msg); - + + /** empty the channel of all requests. + * Typically this is done as soon as input + * is noticed on the channel, because the + * handler will look at a separately managed work + * queue. The actual number of queued "wakeups" + * in the channel will not be important. + */ void drain (); static void drain (int fd); + /** File descriptor that can be used with poll/select to + * detect when wakeup() has been called on this channel. + * It be marked as readable/input-ready when this condition + * is true. It has already been marked non-blocking. + */ + int selectable() const { return fds[0]; } + /* glibmm 2.22 and earlier has a terrifying bug that will cause crashes whenever a Source is removed from a MainContext (including the destruction of the MainContext), @@ -47,15 +87,17 @@ class CrossThreadChannel { the RefPtr. I (Paul) have fixed this (https://bugzilla.gnome.org/show_bug.cgi?id=561885) but in the meantime, we need a hack to get around the issue. */ - Glib::RefPtr ios(); void drop_ios (); + /** returns true if the CrossThreadChannel was + * correctly constructed. + */ bool ok() const { return fds[0] >= 0 && fds[1] >= 0; } private: Glib::RefPtr* _ios; // lazily constructed - int fds[2]; + int fds[2]; // current implementation uses a pipe/fifo }; #endif /* __pbd__crossthread_h__ */ -- cgit v1.2.3