c++-gtk-utils

notifier.h

Go to the documentation of this file.
00001 /* Copyright (C) 2005 to 2011 Chris Vine
00002 
00003 The library comprised in this file or of which this file is part is
00004 distributed by Chris Vine under the GNU Lesser General Public
00005 License as follows:
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public License
00009    as published by the Free Software Foundation; either version 2.1 of
00010    the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License, version 2.1, for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License, version 2.1, along with this library (see the file LGPL.TXT
00019    which came with this source code package in the c++-gtk-utils
00020    sub-directory); if not, write to the Free Software Foundation, Inc.,
00021    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00022 
00023 */
00024 
00025 #ifndef CGU_NOTIFIER_H
00026 #define CGU_NOTIFIER_H
00027 
00028 /**
00029  * @file notifier.h
00030  * @brief This file provides a Notifier class to provide thread-safe
00031  * signalling between a worker thread and the main program thread.
00032  *
00033  * For further details read this: Notifier.
00034  */
00035 
00036 #include <unordered_set>
00037 
00038 #include <pthread.h>
00039 
00040 #include <c++-gtk-utils/pipes.h>
00041 #include <c++-gtk-utils/io_watch.h>
00042 #include <c++-gtk-utils/emitter.h>
00043 #include <c++-gtk-utils/cgu_config.h>
00044 
00045 namespace Cgu {
00046 
00047 /**
00048  * @class Notifier notifier.h c++-gtk-utils/notifier.h
00049  * @brief Provides thread-safe signalling between a worker thread and
00050  * the main program thread.
00051  * @sa Callback namespace Callback::post()
00052  * @sa EmitterArg SafeEmitterArg Releaser
00053  *
00054  * The Notifier class provides thread-safe signalling between two
00055  * threads. It does this through a pipe, to which an GSource (iowatch)
00056  * object is attached to connect it to the glib program event loop.  A
00057  * functor is connected to the notifier, which is called in the
00058  * receiving thread via the program event loop when operator()() (or
00059  * emit()) is called on the Notifier object by the signalling thread.
00060  * It therefore behaves like a SafeEmitter object, except that
00061  * connected functors execute in the glib program event loop thread
00062  * rather than in the thread which calls operator()()/emit().
00063  *
00064  * It is an alternative to the Callback::post() function in
00065  * callback.h, and the documentation on callback.h contains a
00066  * description of relevant trade-offs between the two.
00067  *
00068  * If the signalling thread is the same thread as that in which the
00069  * functor connected to it will execute (which is the thread in which
00070  * the default glib program event loop executes), executing it via the
00071  * pipe would risk a deadlock - if the pipe fills up, the thread would
00072  * block on write and never be able to read from the pipe to empty it.
00073  * Accordingly, if the object is invoked by the same thread as that in
00074  * which the functor will execute, this is detected and the functor
00075  * will be invoked directly, rather than via the pipe.  Therefore,
00076  * actions so invoked may be out of order with those invoked by the
00077  * other threads.
00078  *
00079  * If a Releaser object is passed as the second argument of
00080  * Notifier::connect(), then a connected functor will automatically be
00081  * disconnected if the object which has the Releaser object as a
00082  * member is destroyed.
00083  *
00084  * The main use of Notifier objects is for a worker thread to signal
00085  * an event to the main thread in which GTK+ is executing, which
00086  * implies that GTK+ should also be executing in the default glib
00087  * program event loop (GMainContext) (as will almost always be the
00088  * case), which is the one with which the program first starts.
00089  * Before a Notifier object is first used, it is a requirement that
00090  * Notifier::init() (a static member function) be called in the thread
00091  * in which the default glib event loop executes, and any connected
00092  * functors will execute in that thread.  Notifier::init() only needs
00093  * to be called once at program start-up - it doesn't need to be
00094  * called separately for each Notifier object, and can be called
00095  * before any Notifier objects have been constructed.  If it has not
00096  * been called before the construction of the first Notifier object
00097  * has taken place, it will occur automatically on that first
00098  * construction.  That means that if the first Notifier object is not
00099  * constructed in the main (event loop) thread of the program, then
00100  * Notifier::init() must be called explicitly before that first object
00101  * is constructed.  In addition, if glib < 2.32 is installed, before
00102  * Notifier::init() is called (or the first Notifier object created)
00103  * g_thread_init(0) should have been called: as a result a Notifier
00104  * object cannot be a global (non-local) static object with glib <
00105  * 2.32 (glib >= 2.32 does not require g_thread_init() to be called to
00106  * be thread safe).  It is a good idea also that Notifier::init()
00107  * should have been called (or the first Notifier object constructed)
00108  * before the main program thread creates any new threads.  Then the
00109  * state of initialisation effected by Notifier::init() will
00110  * automatically be visible between threads.
00111  *
00112  * When executing a functor connected to a Notifier object, a check is
00113  * made for a case where between the signalling thread invoking a
00114  * Notifier object and the main program event loop calling that
00115  * functor, the Notifier object ceases to exist.  However there can
00116  * still be a race condition if the lifetime of the Notifier object is
00117  * determined outside the thread of execution of the main program
00118  * event loop and a Notifier object is destroyed by that other thread
00119  * between the time the check is made and the functor executed.
00120  * Normally Notifier objects are constructed and destroyed in the main
00121  * program thread, but where that is not the case the user will need
00122  * to take this into account and if need be provide appropriate
00123  * synchronisation to secure the lifetime of the Notifier object until
00124  * after the functor has been called.  Likewise, a Releaser object
00125  * cannot offer protection if the remote object whose non-static
00126  * method is represented by a connected functor is destroyed by
00127  * another thread while the main program loop is in the middle of
00128  * executing the functor.  When the main loop begins invoking the
00129  * execution of the callback, the remote object must either wholly
00130  * exist (in which case the callback will be invoked) or have been
00131  * destroyed (in which case the callback will be ignored), and not be
00132  * in some transient half-state governed by another thread.
00133  *
00134  * Apart from that, the Notifier object is thread-safe and any of its
00135  * methods may be invoked in any thread.  (It is as thread-safe as a
00136  * SafeEmitter object, as described in emitter.h, which contains
00137  * further details on thread safety.)
00138  *
00139  * To pass variable data to a functor executed by the Notifier object,
00140  * the AsyncQueue class can be employed.
00141 */
00142 
00143 /*
00144   For a program with two GMainContext program event loops (not a usual
00145   case), it would be possible for a Notifier-like object to be
00146   initialised in the non-default GMainContext thread, and execute in
00147   that thread, by passing that other GMainContext object as the last
00148   argument when calling start_iowatch() in Notifier::Notifier().
00149   However, to conserve file descriptors all Notifier objects share a
00150   common pipe and iowatch event watch, which implies that all Notifier
00151   objects would also need to execute in that other thread.  To get
00152   around this it would be possible either to templatize Notifier with
00153   tag types for different GMainContexts (so that there would be a
00154   different static pipe/iowatch object for each GMainContext), or to
00155   have thread-local storage for each of the static objects in the
00156   Notifier class, but an easier solution for one-off cases would be to
00157   have a version of Notifier which does not use static (shared)
00158   PipeFifo and iowatch objects, at the expense of greater use of file
00159   descriptor resources.
00160 
00161   Such a special Notifier object could also be used to signal from a
00162   Unix (asynchronous) signal/interrupt handler, but in that case the
00163   write file descriptor of the pipe should be set non-blocking to
00164   prevent the very unlikely but theoretically possible case (in a
00165   program executing in a system under extreme load) of the pipe
00166   filling up before being emptied by the Notifier::read_pipe_cb()
00167   callback function executing in the main program and so blocking in
00168   the handler, thus deadlocking the program.
00169 */
00170 
00171 
00172 namespace Thread {
00173   class Mutex;
00174 }
00175 
00176 class Notifier;
00177 
00178 class Notifier {
00179 
00180   static bool initialised;
00181   static pthread_t thread_id;
00182   // pointers can be keys of associative containers: "For templates
00183   // greater, less, greater_equal, and less_equal, the specializations
00184   // for any pointer type yield a total order, even if the built-in
00185   // operators <, >, <=, >= do not." (para 20.3.3/8).
00186   static std::unordered_set<Notifier*> object_set;
00187   static PipeFifo pipe;
00188   static Thread::Mutex* set_mutex_p;
00189   static Thread::Mutex* write_mutex_p;
00190   static void read_pipe_cb(bool&);
00191  
00192   SafeEmitter emitter;
00193 public:
00194 /**
00195  * This class cannot be copied.  The copy constructor is deleted.
00196  */
00197   Notifier(const Notifier&) = delete;
00198 
00199 /**
00200  * This class cannot be copied.  The assignment operator is deleted.
00201  */
00202   Notifier& operator=(const Notifier&) = delete;
00203 
00204 /**
00205  * A utility which tells the caller whether it is in the thread in
00206  * which the callback will execute (the main program thread).  It will
00207  * not throw.  It is thread safe.
00208  * @return true if the caller is in the thread in which the callback
00209  * will execute, otherwise false.
00210  */
00211   // don't make this a static member function - it can then only be called
00212   // by object notation after a Notifier object has first been constructed,
00213   // which means Notifier::init() must have been called
00214   bool in_main_thread() {return pthread_equal(thread_id, pthread_self());}
00215 
00216 /**
00217  * This will cause the connected functors to be executed in the main
00218  * program thread.  It is thread safe (but see the comments in the
00219  * introductory remarks above about race conditions where the lifetime
00220  * of a Notifier object is determined by a thread other than the main
00221  * program thread, and about protection by a Releaser object where a
00222  * connected remote object is destroyed in mid-emission by another
00223  * thread).
00224  * @exception std::bad_alloc The method might throw std::bad_alloc if
00225  * memory is exhausted and the system throws in that case, and this
00226  * method is called in the thread in which the functors will execute
00227  * (the main program thread).  In addition, it will throw if the
00228  * function or class methods represented by the functors throw (or if
00229  * the assignment operator of a bound argument throws) and the call is
00230  * made in that thread.  If called in a different thread it will not
00231  * throw (an exception thrown by a connected functor will be caught
00232  * and reported in the iowatch dispatcher).
00233  */
00234   void emit();
00235 
00236 /**
00237  * This will cause the connected functors to be executed in the main
00238  * program thread.  It is thread safe (but see the comments in the
00239  * introductory remarks above about race conditions where the lifetime
00240  * of a Notifier object is determined by a thread other than the main
00241  * program thread, and about protection by a Releaser object where a
00242  * connected remote object is destroyed in mid-emission by another
00243  * thread).
00244  * @exception std::bad_alloc The method might throw std::bad_alloc if
00245  * memory is exhausted and the system throws in that case, and this
00246  * method is called in the thread in which the functors will execute
00247  * (the main program thread).  In addition, it will throw if the
00248  * function or class methods represented by the functors throw (or if
00249  * the assignment operator of a bound argument throws) and the call is
00250  * made in that thread.  If called in a different thread it will not
00251  * throw (an exception thrown by a connected functor will be caught
00252  * and reported in the iowatch dispatcher).
00253  */
00254   void operator()() {emit();}
00255 
00256 /**
00257  * Connects a functor.  It is thread safe.
00258  * @param f The functor to connect.
00259  * @return The functor connected.
00260  * @exception std::bad_alloc The method might throw std::bad_alloc if
00261  * memory is exhausted and the system throws in that case.
00262  */
00263   Callback::SafeFunctor connect(const Callback::SafeFunctor& f);
00264 
00265 /**
00266  * Connects a functor.  It is thread safe.
00267  * @param f The functor to connect.
00268  * @param r A Releaser object for automatic disconnection of the
00269  * functor if the object whose method it represents is destroyed.
00270  * @return The functor connected.
00271  * @exception std::bad_alloc The method might throw std::bad_alloc if
00272  * memory is exhausted and the system throws in that case.
00273  */
00274   Callback::SafeFunctor connect(const Callback::SafeFunctor& f, Releaser& r);
00275 
00276 /**
00277  * Disconnects a functor previously connected. This does not throw
00278  * provided that the destructors of any bound arguments do not throw.
00279  * It is thread safe.
00280  * @param f The functor to disconnect.
00281  */
00282   void disconnect(const Callback::SafeFunctor& f);
00283 
00284 /**
00285  * Blocks a connected functor from executing in the main program
00286  * thread when emit() or operator()() is called until unblock() is
00287  * called.  This method does not throw.  It is thread safe.
00288  * @param f The functor to block.
00289  * @note This has effect immediately: it will block a pending emission
00290  * for which emit() or operator()() has previously been called but
00291  * which has not yet been tested for execution in the main loop.
00292  */
00293   void block(const Callback::SafeFunctor& f);
00294 
00295 /**
00296  * Unblocks a previously blocked functor.  This method does not throw.
00297  * It is thread safe.
00298  * @param f The functor to unblock.
00299  * @note This has effect immediately: it will unblock a pending
00300  * emission for which emit() or operator()() has previously been
00301  * called but which has not yet been tested for execution in the main
00302  * loop.
00303  */
00304   void unblock(const Callback::SafeFunctor& f);
00305 
00306 /**
00307  * Initialises the program for the use of Notifier objects.  It only
00308  * needs to be called once at program start-up (it doesn't need to be
00309  * called separately for each Notifier object), and can be called
00310  * before any Notifier objects have been constructed.  It should be
00311  * called in the thread in which the default main glib event loop
00312  * executes (the main program thread) before that thread creates any
00313  * new threads.
00314  * @exception std::bad_alloc This method might throw std::bad_alloc if
00315  * memory is exhausted and the system throws in that case.
00316  * @exception PipeError PipeError will be thrown if the static pipe
00317  * used by Notifier objects cannot be initialised.
00318  */
00319   static void init();
00320 
00321 /**
00322  * The constructor is thread safe provided init() has previously been
00323  * called before the main program thread creates any new threads.
00324  * @exception std::bad_alloc The constructor might throw
00325  * std::bad_alloc if memory is exhausted and the system throws in that
00326  * case.
00327  * @exception PipeError PipeError can be thrown if this is the first
00328  * Notifier object to be constructed and Notifier::init() has not
00329  * previously been called.
00330  */
00331   Notifier();
00332 
00333 /**
00334  * The destructor does not throw provided the destructors of any bound
00335  * arguments do not throw and std::hash<T*>::operator()() does not
00336  * throw (as it would not on any sane implementation).  It is thread
00337  * safe (but see the comments in the introductory remarks above about
00338  * race conditions where the lifetime of a Notifier object is
00339  * determined by a thread other than the main program thread).
00340  */
00341   ~Notifier();
00342 
00343 /* Only has effect if --with-glib-memory-slices-compat or
00344  * --with-glib-memory-slices-no-compat option picked */
00345   CGU_GLIB_MEMORY_SLICES_FUNCS
00346 };
00347 
00348 } // namespace Cgu
00349 
00350 #endif