c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

notifier.h
Go to the documentation of this file.
1 /* Copyright (C) 2005 to 2013 Chris Vine
2
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License, version 2.1, for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License, version 2.1, along with this library (see the file LGPL.TXT
19 which came with this source code package in the c++-gtk-utils
20 sub-directory); if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 */
24
25 #ifndef CGU_NOTIFIER_H
26 #define CGU_NOTIFIER_H
27
28 /**
29 * @file notifier.h
30 * @brief This file provides a Notifier class to provide thread-safe
31 * signalling between a worker thread and the main program thread.
32 *
33 * For further details read this: Notifier.
34 */
35
36 #include <unordered_set>
37 #include <type_traits> // for std::remove_reference, std::enable_if and std::is_convertible
38
39 #include <pthread.h>
40
41 #include <c++-gtk-utils/pipes.h>
42 #include <c++-gtk-utils/io_watch.h>
43 #include <c++-gtk-utils/emitter.h>
44 #include <c++-gtk-utils/cgu_config.h>
45
46 namespace Cgu {
47
48 /**
49 * @class Notifier notifier.h c++-gtk-utils/notifier.h
50 * @brief Provides thread-safe signalling between a worker thread and
51 * the main program thread.
52 * @sa Callback namespace Callback::post()
53 * @sa EmitterArg SafeEmitterArg Releaser
54 *
55 * The Notifier class provides thread-safe signalling between two
56 * threads. It does this through a pipe, to which an GSource (iowatch)
57 * object is attached to connect it to the glib program event loop.
58 * Callable objects (such as lambda expressions or the return value of
59 * std::bind) or Callback::SafeFunctor objects may be connected to the
60 * Notifier (referred to be below as "connected callables"), which are
61 * called in the receiving thread via the program event loop when
62 * operator()() (or emit()) is called on the Notifier object by the
63 * signalling thread. It therefore behaves like a SafeEmitter object,
64 * except that connected callables execute in the glib program event
65 * loop thread rather than in the thread which calls
66 * operator()()/emit().
67 *
68 * It is an alternative to the Callback::post() function in
69 * callback.h, and the documentation on callback.h contains a
70 * description of relevant trade-offs between the two.
71 *
72 * If the signalling thread is the same thread as that in which the
73 * connected callables will execute (which is the thread in which the
74 * default glib program event loop executes), executing them via the
75 * pipe would risk a deadlock - if the pipe fills up, the thread would
76 * block on write and never be able to read from the pipe to empty it.
77 * Accordingly, if the Notifier object is invoked by the same thread
78 * as that in which the connected callables will execute, this is
79 * detected and they will be invoked directly, rather than via the
80 * pipe. Therefore, actions so invoked may be out of order with those
81 * invoked by the other threads.
82 *
83 * If a Releaser object is passed as the second argument of
84 * Notifier::connect(), then the connected callable concerned will
85 * automatically be disconnected if the object which has the Releaser
86 * object as a member is destroyed.
87 *
88 * The main use of Notifier objects is for a worker thread to signal
89 * an event to the main thread in which GTK+ is executing, which
90 * implies that GTK+ should also be executing in the default glib
91 * program event loop (GMainContext) (as will almost always be the
92 * case), which is the one with which the program first starts.
93 * Before a Notifier object is first used, it is a requirement that
94 * Notifier::init() (a static member function) be called in the thread
95 * in which the default glib event loop executes, and any connected
96 * callables will execute in that thread. Notifier::init() only needs
97 * to be called once at program start-up - it doesn't need to be
98 * called separately for each Notifier object, and can be called
99 * before any Notifier objects have been constructed. If it has not
100 * been called before the construction of the first Notifier object
101 * has taken place, it will occur automatically on that first
102 * construction. That means that if the first Notifier object is not
103 * constructed in the main (event loop) thread of the program, then
104 * Notifier::init() must be called explicitly before that first object
105 * is constructed. In addition, if glib < 2.32 is installed, before
106 * Notifier::init() is called (or the first Notifier object created)
107 * g_thread_init(0) should have been called: as a result a Notifier
108 * object cannot be a global (non-local) static object with glib <
109 * 2.32 (glib >= 2.32 does not require g_thread_init() to be called to
110 * be thread safe). Note also that global static Notifier objects are
111 * not safe prior to version 2.0.15, even with glib >= 2.32.
112 *
113 * It is a good idea that Notifier::init() should have been called (or
114 * the first Notifier object constructed) before the main program
115 * thread creates any new threads. Then the state of initialisation
116 * effected by Notifier::init() will automatically be visible between
117 * threads.
118 *
119 * When executing connected callables, a check is made for a case
120 * where between the signalling thread invoking a Notifier object and
121 * the main program event loop executing the callables, the Notifier
122 * object ceases to exist. However there can still be a race
123 * condition if the lifetime of the Notifier object is determined
124 * outside the thread of execution of the main program event loop and
125 * a Notifier object is destroyed by that other thread between the
126 * time the check is made and the callables executed. Normally
127 * Notifier objects are constructed and destroyed in the main program
128 * thread, but where that is not the case the user will need to take
129 * this into account and if need be provide appropriate
130 * synchronisation to secure the lifetime of the Notifier object until
131 * after the callables have been executed. Likewise, a Releaser
132 * object cannot offer protection if the remote object whose
133 * non-static method is represented or called into by a connected
134 * callable is destroyed by another thread while the main program loop
135 * is in the middle of executing the callable. When the main loop
136 * begins executing a callable, the remote object must either wholly
137 * exist (in which case the callable will be invoked) or have been
138 * destroyed (in which case the callable will be ignored), and not be
139 * in some transient half-state governed by another thread.
140 *
141 * Apart from that, the Notifier object is thread-safe and any of its
142 * methods may be invoked in any thread. (It is as thread-safe as a
143 * SafeEmitter object, as described in emitter.h, which contains
144 * further details on thread safety.)
145 *
146 * To pass variable data to a connected callable, the AsyncQueue class
147 * can be employed.
148 *
149 * @b Usage
150 *
151 * This is an example:
152 *
153 * @code
154 * using namespace Cgu;
155 *
156 * // assume a Notifier object 'notifier' has been constructed at some other point in the program
157 * notifier.connect([] () {std::cout << "Hello world\n";});
158 * notifier(); // callable executes in glib main loop
159 * @endcode
160 *
161 * Callback::SafeFunctor objects may be connected to a notifier, and
162 * the connect() method may be directly initialized with the result of
163 * Callback::make(), Callback::make_ref() or Callback::lambda() and
164 * implicit conversion will take place. Here is an example using
165 * Callback::make_ref(), with a class object my_obj of type MyClass,
166 * with a method void MyClass::my_method(const Something&, int):
167 *
168 * @code
169 * using namespace Cgu;
170 *
171 * int arg1 = 1;
172 * Something arg2;
173 * notifier.connect(Callback::make_ref(my_obj, &MyClass::my_method, arg1, arg2));
174 * notifier(); // callable executes in glib main loop
175 * @endcode
176 *
177 */
178
179 /*
180 For a program with two GMainContext program event loops (not a usual
181 case), it would be possible for a Notifier-like object to be
182 initialised in the non-default GMainContext thread, and execute in
183 that thread, by passing that other GMainContext object as the last
184 argument when calling start_iowatch() in Notifier::Notifier().
185 However, to conserve file descriptors all Notifier objects share a
186 common pipe and iowatch event watch, which implies that all Notifier
187 objects would also need to execute in that other thread. To get
188 around this it would be possible either to templatize Notifier with
189 tag types for different GMainContexts (so that there would be a
190 different static pipe/iowatch object for each GMainContext), or to
191 have thread-local storage for each of the static objects in the
192 Notifier class, but an easier solution for one-off cases would be to
193 have a version of Notifier which does not use static (shared)
194 PipeFifo and iowatch objects, at the expense of greater use of file
195 descriptor resources.
196
197 Such a special Notifier object could also be used to signal from a
198 Unix (asynchronous) signal/interrupt handler, but in that case the
199 write file descriptor of the pipe should be set non-blocking to
200 prevent the very unlikely but theoretically possible case (in a
201 program executing in a system under extreme load) of the pipe
202 filling up before being emptied by the Notifier::read_pipe_cb()
203 callback function executing in the main program and so blocking in
204 the handler, thus deadlocking the program.
205 */
206
207
208 namespace Thread {
209 class Mutex;
210 }
211
212 class Notifier;
213
214 class Notifier {
215
216 static bool initialised;
217 static pthread_t thread_id;
218 // pointers can be keys of associative containers: "For templates
219 // greater, less, greater_equal, and less_equal, the specializations
220 // for any pointer type yield a total order, even if the built-in
221 // operators <, >, <=, >= do not." (para 20.3.3/8).
222 static std::unordered_set<Notifier*>* object_set_p;
223 static PipeFifo* pipe_p;
224 static Thread::Mutex* set_mutex_p;
225 static Thread::Mutex* write_mutex_p;
226 static void read_pipe_cb(bool&);
227
228 SafeEmitter emitter;
229 public:
230 /**
231 * This class cannot be copied. The copy constructor is deleted.
232 */
233 Notifier(const Notifier&) = delete;
234
235 /**
236 * This class cannot be copied. The assignment operator is deleted.
237 */
238 Notifier& operator=(const Notifier&) = delete;
239
240 /**
241 * A utility which tells the caller whether it is in the thread in
242 * which the callback will execute (the main program thread). It will
243 * not throw. It is thread safe.
244 * @return true if the caller is in the thread in which the callback
245 * will execute, otherwise false.
246 */
247 // don't make this a static member function - it can then only be called
248 // by object notation after a Notifier object has first been constructed,
249 // which means Notifier::init() must have been called
250 bool in_main_thread() {return pthread_equal(thread_id, pthread_self());}
251
252 /**
253 * This will cause the connected functors to be executed in the main
254 * program thread. It is thread safe (but see the comments in the
255 * introductory remarks above about race conditions where the lifetime
256 * of a Notifier object is determined by a thread other than the main
257 * program thread, and about protection by a Releaser object where a
258 * connected remote object is destroyed in mid-emission by another
259 * thread).
260 * @exception std::bad_alloc The method might throw std::bad_alloc if
261 * memory is exhausted and the system throws in that case, and this
262 * method is called in the thread in which the functors will execute
263 * (the main program thread). In addition, it will throw if the
264 * function or class methods represented by the functors throw (or if
265 * the assignment operator of a bound argument throws) and the call is
266 * made in that thread. If called in a different thread it will not
267 * throw (an exception thrown by a connected functor will be caught
268 * and reported in the iowatch dispatcher).
269 */
270 void emit();
271
272 /**
273 * This will cause the connected functors to be executed in the main
274 * program thread. It is thread safe (but see the comments in the
275 * introductory remarks above about race conditions where the lifetime
276 * of a Notifier object is determined by a thread other than the main
277 * program thread, and about protection by a Releaser object where a
278 * connected remote object is destroyed in mid-emission by another
279 * thread).
280 * @exception std::bad_alloc The method might throw std::bad_alloc if
281 * memory is exhausted and the system throws in that case, and this
282 * method is called in the thread in which the functors will execute
283 * (the main program thread). In addition, it will throw if the
284 * function or class methods represented by the functors throw (or if
285 * the assignment operator of a bound argument throws) and the call is
286 * made in that thread. If called in a different thread it will not
287 * throw (an exception thrown by a connected functor will be caught
288 * and reported in the iowatch dispatcher).
289 */
290 void operator()() {emit();}
291
292 /**
293 * Connects a functor. It is thread safe.
294 * @param f The functor to connect.
295 * @return The functor connected.
296 * @exception std::bad_alloc The method might throw std::bad_alloc if
297 * memory is exhausted and the system throws in that case.
298 */
299 Callback::SafeFunctor connect(const Callback::SafeFunctor& f);
300
301 /**
302 * Connects a functor. It is thread safe.
303 * @param f The functor to connect.
304 * @param r A Releaser object for automatic disconnection of the
305 * functor if the object whose method it represents is destroyed.
306 * @return The functor connected.
307 * @exception std::bad_alloc The method might throw std::bad_alloc if
308 * memory is exhausted and the system throws in that case.
309 */
310 Callback::SafeFunctor connect(const Callback::SafeFunctor& f, Releaser& r);
311
312 /**
313 * Connects a callable object, such as formed by a lambda expression
314 * or the result of std::bind.
315 * @param f The callable object to connect. It must be fully bound
316 * (that is, take no arguments when called).
317 * @return A Callback::SafeFunctor object which can be passed to
318 * disconnect(), block() or unblock().
319 * @exception std::bad_alloc The method might throw std::bad_alloc if
320 * memory is exhausted and the system throws in that case. If might
321 * also throw if the copy or move constructor of the callable object
322 * throws.
323 *
324 * Since 2.1.0
325 */
326 // we need to use enable_if so that where this function is passed a
327 // Callback::SafeFunctor object or a pointer to a Callback::Callback
328 // object or some other convertible object, this templated overload is
329 // dropped from the overload set, in order to support the
330 // Callback::SafeFunctor overloads of this function. This overload
331 // calls into the version of this function taking a
332 // Callback::SafeFunctor object in order to perform type erasure.
333 template <class F,
334 class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<F>::type,
335 const Callback::SafeFunctor>::value>::type>
336 Callback::SafeFunctor connect(F&& f) {
337 return connect(Callback::lambda<>(std::forward<F>(f)));
338 }
339
340 /**
341 * Connects a callable object, such as formed by a lambda expression
342 * or the result of std::bind.
343 * @param f The callable object to connect. It must be fully bound
344 * (that is, take no arguments when called).
345 * @param r A Releaser object for automatic disconnection of the
346 * callable object if an object whose method it represents or calls
347 * into is destroyed.
348 * @return A Callback::SafeFunctor object which can be passed to
349 * disconnect(), block() or unblock().
350 * @exception std::bad_alloc The method might throw std::bad_alloc if
351 * memory is exhausted and the system throws in that case. If might
352 * also throw if the copy or move constructor of the callable object
353 * throws.
354 *
355 * Since 2.1.0
356 */
357 // we need to use enable_if so that where this function is passed a
358 // Callback::SafeFunctor object or a pointer to a Callback::Callback
359 // object or some other convertible object, this templated overload is
360 // dropped from the overload set, in order to support the
361 // Callback::SafeFunctor overloads of this function. This overload
362 // calls into the version of this function taking a
363 // Callback::SafeFunctor object in order to perform type erasure.
364 template <class F,
365 class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<F>::type,
366 const Callback::SafeFunctor>::value>::type>
367 Callback::SafeFunctor connect(F&& f, Releaser& r) {
368 return connect(Callback::lambda<>(std::forward<F>(f)), r);
369 }
370
371 /**
372 * Disconnects a functor previously connected. This does not throw
373 * provided that the destructors of any bound arguments do not throw.
374 * It is thread safe.
375 * @param f The functor to disconnect.
376 */
377 void disconnect(const Callback::SafeFunctor& f);
378
379 /**
380 * Blocks a connected functor from executing in the main program
381 * thread when emit() or operator()() is called until unblock() is
382 * called. This method does not throw. It is thread safe.
383 * @param f The functor to block.
384 * @note This has effect immediately: it will block a pending emission
385 * for which emit() or operator()() has previously been called but
386 * which has not yet been tested for execution in the main loop.
387 */
388 void block(const Callback::SafeFunctor& f);
389
390 /**
391 * Unblocks a previously blocked functor. This method does not throw.
392 * It is thread safe.
393 * @param f The functor to unblock.
394 * @note This has effect immediately: it will unblock a pending
395 * emission for which emit() or operator()() has previously been
396 * called but which has not yet been tested for execution in the main
397 * loop.
398 */
399 void unblock(const Callback::SafeFunctor& f);
400
401 /**
402 * Initialises the program for the use of Notifier objects. It only
403 * needs to be called once at program start-up (it doesn't need to be
404 * called separately for each Notifier object), and can be called
405 * before any Notifier objects have been constructed. It should be
406 * called in the thread in which the default main glib event loop
407 * executes (the main program thread) before that thread creates any
408 * new threads.
409 * @exception std::bad_alloc This method might throw std::bad_alloc if
410 * memory is exhausted and the system throws in that case.
411 * @exception PipeError PipeError will be thrown if the static pipe
412 * used by Notifier objects cannot be initialised.
413 */
414 static void init();
415
416 /**
417 * The constructor is thread safe provided init() has previously been
418 * called before the main program thread creates any new threads.
419 * @exception std::bad_alloc The constructor might throw
420 * std::bad_alloc if memory is exhausted and the system throws in that
421 * case.
422 * @exception PipeError PipeError can be thrown if this is the first
423 * Notifier object to be constructed and Notifier::init() has not
424 * previously been called.
425 */
426 Notifier();
427
428 /**
429 * The destructor does not throw provided the destructors of any bound
430 * arguments do not throw and std::hash<T*>::operator()() does not
431 * throw (as it would not on any sane implementation). It is thread
432 * safe (but see the comments in the introductory remarks above about
433 * race conditions where the lifetime of a Notifier object is
434 * determined by a thread other than the main program thread).
435 */
436 ~Notifier();
437
438 /* Only has effect if --with-glib-memory-slices-compat or
439 * --with-glib-memory-slices-no-compat option picked */
440 CGU_GLIB_MEMORY_SLICES_FUNCS
441 };
442
443 } // namespace Cgu
444
445 #endif