c++-gtk-utils
|
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 59 Temple Place - Suite 330, Boston, MA, 02111-1307, 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() in callback.h, and the 00065 * documentation on callback.h contains a description of relevant 00066 * 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 the main Glib program event loop executes), executing it via 00071 * the pipe would risk a deadlock - if the pipe fills up, the thread 00072 * would block on write and never be able to read from the pipe to 00073 * empty it. Accordingly, if the object is invoked by the same thread 00074 * as that in which the functor will execute, this is detected and the 00075 * functor will be invoked directly, rather than via the pipe. 00076 * Therefore, actions so invoked may be out of order with those 00077 * invoked by the 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 main Glib event loop executes, and any 00092 * connected slots will execute in that thread. Notifier::init() only 00093 * needs 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. Before Notifier::init() is called (or the first 00102 * Notifier object created) g_thread_init(0) should have been called: 00103 * as a result a Notifier object cannot be a global (non-local) static 00104 * object. It is a good idea also that Notifier::init() should have 00105 * been called (or the first Notifier object constructed) before the 00106 * main program thread creates any new threads. Then the state of 00107 * initialisation effected by Notifier::init() will automatically be 00108 * visible between threads. 00109 * 00110 * When executing a functor connected to a Notifier object, a check is 00111 * made for a case where between the signalling thread invoking a 00112 * Notifier object and the main program event loop calling that 00113 * functor, the Notifier object ceases to exist. However there can 00114 * still be a race condition if the lifetime of the Notifier object is 00115 * determined outside the thread of execution of the main program 00116 * event loop and a Notifier object is destroyed by that other thread 00117 * between the time the check is made and the functor executed. 00118 * Normally Notifier objects are constructed and destroyed in the main 00119 * program thread, but where that is not the case the user will need 00120 * to take this into account and if need be provide appropriate 00121 * synchronisation to secure the lifetime of the Notifier object until 00122 * after the functor has been called. Likewise, a Releaser object 00123 * cannot offer protection if the remote object whose non-static 00124 * method is represented by a connected functor is destroyed by 00125 * another thread while the main program loop is in the middle of 00126 * executing the functor. When the main loop begins invoking the 00127 * execution of the callback, the remote object must either wholly 00128 * exist (in which case the callback will be invoked) or have been 00129 * destroyed (in which case the callback will be ignored), and not be 00130 * in some transient half-state governed by another thread. 00131 * 00132 * Apart from that, the Notifier object is thread-safe and any of its 00133 * methods may be invoked in any thread. (It is as thread-safe as a 00134 * SafeEmitter object, as described in emitter.h, which contains 00135 * further details on thread safety.) 00136 * 00137 * To pass variable data to a functor executed by the Notifier object, 00138 * the AsyncQueue class can be employed. 00139 */ 00140 00141 /* 00142 For a program with two GMainContext program event loops (not a usual 00143 case), it would be possible for a Notifier-like object to be 00144 initialised in the non-default GMainContext thread, and execute in 00145 that thread, by passing that other GMainContext object as the last 00146 argument when calling start_iowatch() in Notifier::Notifier(). 00147 However, to conserve file descriptors all Notifier objects share a 00148 common pipe and iowatch event watch, which implies that all Notifier 00149 objects would also need to execute in that other thread. To get 00150 around this it would be possible either to templatize Notifier with 00151 tag types for different GMainContexts (so that there would be a 00152 different static pipe/iowatch object for each GMainContext), or to 00153 have thread-local storage for each of the static objects in the 00154 Notifier class, but an easier solution for one-off cases would be to 00155 have a version of Notifier which does not use static (shared) 00156 PipeFifo and iowatch objects, at the expense of greater use of file 00157 descriptor resources. 00158 00159 Such a special Notifier object could also be used to signal from a 00160 Unix (asynchronous) signal/interrupt handler, but in that case the 00161 write file descriptor of the pipe should be set non-blocking to 00162 prevent the very unlikely but theoretically possible case (in a 00163 program executing in a system under extreme load) of the pipe 00164 filling up before being emptied by the Notifier::read_pipe_cb() 00165 callback function executing in the main program and so blocking in 00166 the handler, thus deadlocking the program. 00167 */ 00168 00169 00170 namespace Thread { 00171 class Mutex; 00172 } 00173 00174 class Notifier; 00175 00176 class Notifier { 00177 00178 static bool initialised; 00179 static pthread_t thread_id; 00180 // pointers can be keys of associative containers: "For templates 00181 // greater, less, greater_equal, and less_equal, the specializations 00182 // for any pointer type yield a total order, even if the built-in 00183 // operators <, >, <=, >= do not." (para 20.3.3/8). 00184 static std::unordered_set<Notifier*> object_set; 00185 static PipeFifo pipe; 00186 static Thread::Mutex* set_mutex_p; 00187 static Thread::Mutex* write_mutex_p; 00188 static void read_pipe_cb(bool&); 00189 00190 SafeEmitter emitter; 00191 public: 00192 /** 00193 * This class cannot be copied. The copy constructor is deleted. 00194 */ 00195 Notifier(const Notifier&) = delete; 00196 00197 /** 00198 * This class cannot be copied. The assignment operator is deleted. 00199 */ 00200 Notifier& operator=(const Notifier&) = delete; 00201 00202 /** 00203 * A utility which tells the caller whether it is in the thread in 00204 * which the callback will execute (the main program thread). It will 00205 * not throw. It is thread safe. 00206 * @return true if the caller is in the thread in which the callback 00207 * will execute, otherwise false. 00208 */ 00209 // don't make this a static member function - it can then only be called 00210 // by object notation after a Notifier object has first been constructed, 00211 // which means Notifier::init() must have been called 00212 bool in_main_thread() {return pthread_equal(thread_id, pthread_self());} 00213 00214 /** 00215 * This will cause the connected functors to be executed in the main 00216 * program thread. It is thread safe (but see the comments in the 00217 * introductory remarks above about race conditions where the lifetime 00218 * of a Notifier object is determined by a thread other than the main 00219 * program thread, and about protection by a Releaser object where a 00220 * connected remote object is destroyed in mid-emission by another 00221 * thread). 00222 * @exception std::bad_alloc The method might throw std::bad_alloc if 00223 * memory is exhausted and the system throws in that case, and this 00224 * method is called in the thread in which the functors will execute 00225 * (the main program thread). In addition, it will throw if the 00226 * function or class methods represented by the functors throw (or if 00227 * the assignment operator of a bound argument throws) and the call is 00228 * made in that thread. If called in a different thread it will not 00229 * throw (an exception thrown by a connected functor will be caught 00230 * and reported in the iowatch dispatcher). 00231 */ 00232 void emit(); 00233 00234 /** 00235 * This will cause the connected functors to be executed in the main 00236 * program thread. It is thread safe (but see the comments in the 00237 * introductory remarks above about race conditions where the lifetime 00238 * of a Notifier object is determined by a thread other than the main 00239 * program thread, and about protection by a Releaser object where a 00240 * connected remote object is destroyed in mid-emission by another 00241 * thread). 00242 * @exception std::bad_alloc The method might throw std::bad_alloc if 00243 * memory is exhausted and the system throws in that case, and this 00244 * method is called in the thread in which the functors will execute 00245 * (the main program thread). In addition, it will throw if the 00246 * function or class methods represented by the functors throw (or if 00247 * the assignment operator of a bound argument throws) and the call is 00248 * made in that thread. If called in a different thread it will not 00249 * throw (an exception thrown by a connected functor will be caught 00250 * and reported in the iowatch dispatcher). 00251 */ 00252 void operator()() {emit();} 00253 00254 /** 00255 * Connects a functor. It is thread safe. 00256 * @param f The functor to connect. 00257 * @return The functor connected. 00258 * @exception std::bad_alloc The method might throw std::bad_alloc if 00259 * memory is exhausted and the system throws in that case. 00260 */ 00261 Callback::SafeFunctor connect(const Callback::SafeFunctor& f); 00262 00263 /** 00264 * Connects a functor. It is thread safe. 00265 * @param f The functor to connect. 00266 * @param r A Releaser object for automatic disconnection of the 00267 * functor if the object whose method it represents is destroyed. 00268 * @return The functor connected. 00269 * @exception std::bad_alloc The method might throw std::bad_alloc if 00270 * memory is exhausted and the system throws in that case. 00271 */ 00272 Callback::SafeFunctor connect(const Callback::SafeFunctor& f, Releaser& r); 00273 00274 /** 00275 * Disconnects a functor previously connected. This does not throw 00276 * provided that the destructors of any bound arguments do not throw. 00277 * It is thread safe. 00278 * @param f The functor to disconnect. 00279 */ 00280 void disconnect(const Callback::SafeFunctor& f); 00281 00282 /** 00283 * Blocks a connected functor from executing in the main program 00284 * thread when emit() or operator()() is called until unblock() is 00285 * called. This method does not throw. It is thread safe. 00286 * @param f The functor to block. 00287 * @note This has effect immediately: it will block a pending emission 00288 * for which emit() or operator()() has previously been called but 00289 * which has not yet been tested for execution in the main loop. 00290 */ 00291 void block(const Callback::SafeFunctor& f); 00292 00293 /** 00294 * Unblocks a previously blocked functor. This method does not throw. 00295 * It is thread safe. 00296 * @param f The functor to unblock. 00297 * @note This has effect immediately: it will unblock a pending 00298 * emission for which emit() or operator()() has previously been 00299 * called but which has not yet been tested for execution in the main 00300 * loop. 00301 */ 00302 void unblock(const Callback::SafeFunctor& f); 00303 00304 /** 00305 * Initialises the program for the use of Notifier objects. It only 00306 * needs to be called once at program start-up (it doesn't need to be 00307 * called separately for each Notifier object), and can be called 00308 * before any Notifier objects have been constructed. It should be 00309 * called in the thread in which the default main Glib event loop 00310 * executes (the main program thread) before that thread creates any 00311 * new threads. 00312 * @exception std::bad_alloc This method might throw std::bad_alloc if 00313 * memory is exhausted and the system throws in that case. 00314 * @exception PipeError PipeError will be thrown if the static pipe 00315 * used by Notifier objects cannot be initialised. 00316 */ 00317 static void init(); 00318 00319 /** 00320 * The constructor is thread safe provided init() has previously been 00321 * called before the main program thread creates any new threads. 00322 * @exception std::bad_alloc The constructor might throw 00323 * std::bad_alloc if memory is exhausted and the system throws in that 00324 * case. 00325 * @exception PipeError PipeError can be thrown if this is the first 00326 * Notifier object to be constructed and Notifier::init() has not 00327 * previously been called. 00328 */ 00329 Notifier(); 00330 00331 /** 00332 * The destructor does not throw provided the destructors of any bound 00333 * arguments do not throw and std::hash<T*>::operator()() does not 00334 * throw (as it would not on any sane implementation). It is thread 00335 * safe (but see the comments in the introductory remarks above about 00336 * race conditions where the lifetime of a Notifier object is 00337 * determined by a thread other than the main program thread). 00338 */ 00339 ~Notifier(); 00340 00341 /* Only has effect if --with-glib-memory-slices-compat or 00342 * --with-glib-memory-slices-no-compat option picked */ 00343 CGU_GLIB_MEMORY_SLICES_FUNCS 00344 }; 00345 00346 } // namespace Cgu 00347 00348 #endif