c++-gtk-utils

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

- File List
- File Members

thread.h
Go to the documentation of this file.
1 /* Copyright (C) 2005 to 2015 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_THREAD_H
26 #define CGU_THREAD_H
27
28 #include <memory> // for std::unique_ptr
29 #include <utility> // for std::move
30
31 #include <pthread.h>
32
33 #include <c++-gtk-utils/callback.h>
34 #include <c++-gtk-utils/mutex.h>
35 #include <c++-gtk-utils/cgu_config.h>
36
37 namespace Cgu {
38
39 namespace Thread {
40
41 /**
42 * @class Cgu::Thread::Thread thread.h c++-gtk-utils/thread.h
43 * @brief A class representing a pthread thread.
44 * @sa Thread::Mutex Thread::Mutex::Lock Thread::Cond Thread::Future Thread::JoinableHandle
45 *
46 * The Thread class encapsulates a pthread thread. It can start, join
47 * and cancel a thread.
48 *
49 * The Thread class, and the other thread related classes provided by
50 * this library such as Mutex, RecMutex, RWLock, CancelBlock and Cond,
51 * can be used interchangeably with (and mixed with) GThread objects
52 * and functions, and with GMutex, GRecMutex, GRWLock, GCond and
53 * similar, as they all use pthreads underneath on POSIX and other
54 * unix-like OSes.
55 *
56 * In addition, the thread related classes provided by this library
57 * can be used in conjunction with threads started with C++11/14
58 * threading facilities, and vice versa, as in C++11/14 on unix-like
59 * OSes these facilities are likely to be built on top of pthreads
60 * (for which purpose C++11/14 provides the std::native_handle_type
61 * type and std::thread::native_handle() function). Even where they
62 * are not, they will use the same threading primitives provided by
63 * the kernel: §30.3 of the C++11 standard states, albeit
64 * non-normatively, that "These threads [std::thread threads] are
65 * intended to map one-to-one with operating system threads".
66 *
67 * If in doubt, always use this library's thread related classes as
68 * they are guaranteed to be compatible with glib/gtk and with the
69 * native platform libraries. However, such doubts are in practice
70 * unnecessary: it is in practice inconceivable that C++11/14's
71 * threading implementation will be incompatible with the platform's
72 * native threading implementation (pthreads), because any practical
73 * program using C++11/14 threads is going to call into platform
74 * libraries, and those libraries may themselves be threaded or make
75 * thread related calls. So use whichever appears to suit the
76 * particular case better.
77 *
78 * @anchor ThreadsAnchor
79 * @b c++-gtk-utils @b library @b and @b C++11/14 @b threads
80 *
81 * As mentioned above, the thread facilities provided by this library
82 * can be freely interchanged with the threading facilities provided
83 * by C++11/14.
84 *
85 * The main features available from this library and not C++11/14 are
86 * thread cancellation and the associated Cgu::Thread::CancelBlock
87 * class, the Cgu::Thread::JoinableHandle class for scoped joinable
88 * thread handling and the Cgu::Thread::TaskManager class for running
89 * and composing tasks on a thread pool.
90 *
91 * C++11/14 does not provide thread cancellation or interruption
92 * support, and C++ will never be able to do so on a complete basis
93 * because to do so requires support from the underlying OS, which
94 * therefore makes it platform specific (in this case, POSIX
95 * specific): cancellation is only of limited use if it cannot
96 * reliably interrupt blocking system calls. The POSIX specification
97 * sets out the interruptible cancellation points in System
98 * Interfaces, section 2.9.5, Cancellation Points, and in effect
99 * specifies all the system calls which can block as cancellation
100 * points.
101 *
102 * Whether, in C++ programs, destructors of local objects in the
103 * cancelled thread are called is also system specific and is not
104 * specified by POSIX. Most modern commercial unixes, and recent
105 * linux/BSD distributions based on NPTL (in the case of Linux, those
106 * based on 2.6/3.x/4.x kernels), will unwind the stack and call
107 * destructors on thread cancellation by means of a pseudo-exception,
108 * but older distributions relying on the former linuxthreads
109 * implementation will not. Therefore for maximum portability
110 * cancellation would only be used where there are plain data
111 * structures/built-in types in existence in local scope when it
112 * occurs, and if there is anything in free store to be released
113 * clean-ups would be implemented with
114 * pthread_cleanup_push()/pthread_cleanup_pop(). This should be
115 * controlled with pthread_setcancelstate() and/or the CancelBlock
116 * class to choose the cancellation point.
117 *
118 * One of the (perhaps odd) features of C++11/14 threads is that if
119 * the destructor of a std::thread object is called which represents a
120 * joinable thread which has not been detach()ed or join()ed, the
121 * whole program is terminated with a call to std::terminate(), which
122 * makes it difficult to use in the presence of exceptions. Often
123 * what is wanted however is for join() to be called on a joinable
124 * thread where the associated thread object goes out of scope, or
125 * (provided it is done carefully and knowingly) for detach() to be
126 * called. The Cgu::Thread::JoinableHandle class can be used where
127 * either of these two is the appropriate response to this situation.
128 *
129 * In addition, the c++-gtk-utils library provides the following which
130 * are not present in C++11 and/or C++14: a guaranteed monotonic clock
131 * on timed condition variable waits where the operating system
132 * supports them; read-write locks/shared mutexes (present in C++14
133 * but not C++11); a Cgu::Thread::Future object which is more
134 * intuitive to use than C++11/14 futures and features a built in
135 * Cgu::SafeEmitter object which emits when the particular task has
136 * completed, and (since version 2.0.2) has associated
137 * Cgu::Thread::Future::when() methods for passing the result to a
138 * glib main loop; and (since version 2.2.2)
139 * Cgu::Thread::parallel_for_each() and
140 * Cgu::Thread::parallel_transform() functions for use with
141 * Cgu::Thread::TaskManager objects.
142 *
143 * @b c++-gtk-utils @b library @b and @b gthreads
144 *
145 * As mentioned above, the thread facilities provided by this library
146 * can be freely interchanged with the threading facilities provided
147 * by glib.
148 *
149 * The main features available with this thread implementation and not
150 * GThreads are thread cancellation, the mutex scoped locking classes
151 * Cgu::Thread::Mutex::Lock and Cgu::Thread::RecMutex::Lock, the
152 * joinable thread scoped management class Cgu::Thread::JoinableHandle
153 * and the Cgu::Thread::Future class (abstracting thread functions
154 * which provide a result).
155 *
156 * There is no need from the perspective of this class to call
157 * g_thread_init() before Cgu::Thread::Thread::start() is called, but
158 * prior to glib version 2.32 glib itself is not thread-safe without
159 * g_thread_init(), so where this class is used with glib < 2.32,
160 * g_thread_init() should be called at program initialization.
161 *
162 * See @ref Threading for particulars about GTK+ thread safety.
163 */
164
165
166 class Thread {
167 pthread_t thread;
168 // private constructor - this class can only be created with Thread::start
169 Thread() {}
170 public:
171 /**
172 * This class cannot be copied: it is intended to be held by
173 * std::unique_ptr. The copy constructor is deleted.
174 */
175 Thread(const Thread&) = delete;
176
177 /**
178 * This class cannot be copied: it is intended to be held by
179 * std::unique_ptr. The assignment operator is deleted.
180 */
181 Thread& operator=(const Thread&) = delete;
182
183 /**
184 * Cancels the thread represented by this Thread object. It can be
185 * called by any thread. The effect is undefined if the thread
186 * represented by this Thread object has both (a) already terminated
187 * and (b) been detached or had a call to join() made for it.
188 * Accordingly, if the user is not able to establish from the program
189 * logic whether the thread has terminated, the thread must be created
190 * as joinable and cancel() must not be called after a call to
191 * detach() has been made or a call to join() has returned. A
192 * Thread::JoinableHandle object can used to ensure this. It does not
193 * throw.
194 * @note 1. Use this method with care - sometimes its use is
195 * unavoidable but destructors for local objects may not be called if
196 * a thread exits by virtue of a call to cancel() (that depends on the
197 * implementation). Most modern commercial unixes, and recent
198 * linux/BSD distributions based on NPTL, will unwind the stack and
199 * call destructors on thread cancellation by means of a
200 * pseudo-exception, but older distributions relying on the former
201 * linuxthreads implementation will not. Therefore for maximum
202 * portability only have plain data structures/built-in types in
203 * existence in local scope when it occurs and if there is anything in
204 * free store to be released implement clean-ups with
205 * pthread_cleanup_push()/pthread_cleanup_pop(). This should be
206 * controlled with pthread_setcancelstate() and/or the CancelBlock
207 * class to choose the cancellation point.
208 * @note 2. When using thread cancellation, do not allow a
209 * cancellation pseudo-exception to propagate through a function with
210 * a 'noexcept' or 'noexcept(true)' specifier, as the cancellation
211 * pseudo-exception would be incompatible with such a specifier and
212 * std::terminate may be called.
213 * @sa Cgu::Thread::Exit
214 */
215 void cancel() noexcept {pthread_cancel(thread);}
216
217 /**
218 * Joins the thread represented by this Thread object (that is, waits
219 * for it to terminate). It can only be called by one thread, which
220 * can be any thread other than the one represented by this Thread
221 * object. The result is undefined if the thread represented by this
222 * Thread object is or was detached or join() has already been called
223 * for it (a Thread::JoinableHandle object will however give a defined
224 * result in such cases for threads originally started as joinable).
225 * It does not throw.
226 */
227 void join() noexcept {pthread_join(thread, 0);}
228
229 /**
230 * Detaches the thread represented by this Thread object where it is
231 * joinable, so as to make it unjoinable. The effect is undefined if
232 * the thread is already unjoinable (a Thread::JoinableHandle object
233 * will however give a defined result in such cases for threads
234 * originally started as joinable). It does not throw.
235 */
236 void detach() noexcept {pthread_detach(thread);}
237
238 /**
239 * Specifies whether the calling thread is the same thread as is
240 * represented by this Thread object. The effect is undefined if the
241 * thread represented by this Thread object has both (a) already
242 * terminated and (b) been detached or had a call to join() made for
243 * it. Accordingly, if the user is not able to establish from the
244 * program logic whether the thread has terminated, the thread must be
245 * created as joinable and is_caller() must not be called after a call
246 * to detach() has been made or a call to join() has returned. A
247 * Thread::JoinableHandle object can used to ensure this. This method
248 * does not throw.
249 * @return Returns true if the caller is in the thread represented by
250 * this Thread object.
251 */
252 bool is_caller() noexcept {return pthread_equal(thread, pthread_self());}
253
254 /**
255 * Starts a new thread. It can be called by any thread.
256 * @param cb A callback object (created by Callback::make(),
257 * Callback::make_ref() or Callback::lambda()) encapsulating the
258 * function to be executed by the new thread. The Thread object
259 * returned by this function will take ownership of the callback: it
260 * will automatically be deleted either by the new thread when it has
261 * finished with it, or by this method in the calling thread if the
262 * attempt to start a new thread fails (including if std::bad_alloc is
263 * thrown).
264 * @param joinable Whether the join() method may be called in relation
265 * to the new thread.
266 * @return A Thread object representing the new thread which has been
267 * started, held by a std::unique_ptr object as it has single
268 * ownership semantics. The std::unique_ptr object will be empty
269 * (that is std::unique_ptr<Cgu::Thread::Thread>::get() will return 0)
270 * if the thread did not start correctly, which would mean that memory
271 * is exhausted, the pthread thread limit has been reached or pthread
272 * has run out of other resources to start new threads.
273 * @exception std::bad_alloc This method might throw std::bad_alloc if
274 * memory is exhausted and the system throws in that case. (This
275 * exception will not be thrown if the library has been installed
276 * using the \--with-glib-memory-slices-no-compat configuration
277 * option: instead glib will terminate the program if it is unable to
278 * obtain memory from the operating system.) If this exception is
279 * thrown, the thread will not have started.
280 * @note 1. The thread will keep running even if the return value of
281 * start() goes out of scope (but it will no longer be possible to
282 * call any of the methods in this class for it, which is fine if the
283 * thread is not started as joinable and it is not intended to cancel
284 * it).
285 * @note 2. If the thread is started with the joinable attribute, the
286 * user must subsequently either call the join() or the detach()
287 * method, as otherwise a resource leak may occur (the destructor of
288 * this class does not call detach() automatically). Alternatively,
289 * the return value of this method can be passed to a
290 * Thread::JoinableHandle object which will do this automatically in
291 * the Thread::JoinableHandle object's destructor.
292 * @note 3. Any Thread::Exit exception thrown from the function
293 * executed by the new thread will be caught and consumed. The thread
294 * will safely terminate and unwind the stack in so doing.
295 * @note 4. If any uncaught exception other than Thread::Exit is
296 * allowed to propagate from the initial function executed by the new
297 * thread, the exception is not consumed (NPTL's forced stack
298 * unwinding on cancellation does not permit catching with an ellipsis
299 * argument without rethrowing, and even if it did permit it, the
300 * result would be an unreported error). The C++11 standard requires
301 * std::terminate() to be called in such a case and so the entire
302 * program terminated. Accordingly, a user must make sure that no
303 * exceptions, other than Thread::Exit or any cancellation
304 * pseudo-exception, can propagate from the initial function executed
305 * by the new thread. This includes ensuring that, for any argument
306 * passed to that function which is not a built-in type and which is
307 * not taken by the function by const or non-const reference, the
308 * argument type's copy constructor does not throw.
309 */
310 static std::unique_ptr<Cgu::Thread::Thread> start(const Cgu::Callback::Callback* cb,
311 bool joinable);
312
313 /**
314 * Starts a new thread. It can be called by any thread.
315 * @param func A callable object, such as formed by a lambda
316 * expression or the result of std::bind, which will be executed by
317 * the new thread.
318 * @param joinable Whether the join() method may be called in relation
319 * to the new thread.
320 * @return A Thread object representing the new thread which has been
321 * started, held by a std::unique_ptr object as it has single
322 * ownership semantics. The std::unique_ptr object will be empty
323 * (that is std::unique_ptr<Cgu::Thread::Thread>::get() will return 0)
324 * if the thread did not start correctly, which would mean that memory
325 * is exhausted, the pthread thread limit has been reached or pthread
326 * has run out of other resources to start new threads.
327 * @exception std::bad_alloc This method might throw std::bad_alloc if
328 * memory is exhausted and the system throws in that case. (This
329 * exception will not be thrown if the library has been installed
330 * using the \--with-glib-memory-slices-no-compat configuration
331 * option: instead glib will terminate the program if it is unable to
332 * obtain memory from the operating system.) If this exception is
333 * thrown, the thread will not have started.
334 * @note 1. This function may also throw if the copy or move
335 * constructor of the callable object throws. If that happens, the
336 * thread will not have started.
337 * @note 2. The thread will keep running even if the return value of
338 * start() goes out of scope (but it will no longer be possible to
339 * call any of the methods in this class for it, which is fine if the
340 * thread is not started as joinable and it is not intended to cancel
341 * it).
342 * @note 3. If the thread is started with the joinable attribute, the
343 * user must subsequently either call the join() or the detach()
344 * method, as otherwise a resource leak may occur (the destructor of
345 * this class does not call detach() automatically). Alternatively,
346 * the return value of this method can be passed to a
347 * Thread::JoinableHandle object which will do this automatically in
348 * the Thread::JoinableHandle object's destructor.
349 * @note 4. Any Thread::Exit exception thrown from the function
350 * executed by the new thread will be caught and consumed. The thread
351 * will safely terminate and unwind the stack in so doing.
352 * @note 5. If any uncaught exception other than Thread::Exit is
353 * allowed to propagate from the initial function executed by the new
354 * thread, the exception is not consumed (NPTL's forced stack
355 * unwinding on cancellation does not permit catching with an ellipsis
356 * argument without rethrowing, and even if it did permit it, the
357 * result would be an unreported error). The C++11 standard requires
358 * std::terminate() to be called in such a case and so the entire
359 * program terminated. Accordingly, a user must make sure that no
360 * exceptions, other than Thread::Exit or any cancellation
361 * pseudo-exception, can propagate from the initial function executed
362 * by the new thread. This includes ensuring that, for any bound
363 * argument passed to that function which is not a built-in type and
364 * which is not taken by the function by const or non-const reference,
365 * the argument type's copy constructor does not throw.
366 *
367 * Since 2.1.0
368 */
369 // we need to use enable_if so that where this function is passed a
370 // pointer to non-const Callback::Callback, or some other convertible
371 // pointer, this templated overload is dropped from the overload set,
372 // in order to support the Callback::Callback pointer overloads of
373 // this function. This overload calls into the version of this
374 // function taking a pointer to const Callback::Callback in order to
375 // perform type erasure.
376 template <class F,
377 class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<F>::type,
378 const Cgu::Callback::Callback*>::value>::type>
379 static std::unique_ptr<Cgu::Thread::Thread> start(F&& func,
380 bool joinable) {
381 return start(Cgu::Callback::lambda<>(std::forward<F>(func)), joinable);
382 }
383
384 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
385 CGU_GLIB_MEMORY_SLICES_FUNCS
386 #endif
387 };
388
389 /**
390 * @class Cgu::Thread::JoinableHandle thread.h c++-gtk-utils/thread.h
391 * @brief A class wrapping a Thread::Thread object representing a
392 * joinable thread.
393 * @sa Thread::Thread Thread::Future
394 *
395 * This class enables a joinable thread to be made more easily
396 * exception safe. It can also be used to provide that a joinable
397 * thread is not detached or joined while other methods dependent on
398 * that might still be called, and to provide a defined result where
399 * there are multiple calls to join() and/or detach(). When it is
400 * destroyed, it will either detach or join the thread represented by
401 * the wrapped Thread::Thread object unless it has previously been
402 * detached or joined using the detach() or join() methods, so
403 * avoiding thread resource leaks. Whether it will detach() or join()
404 * on destruction depends on the Thread::JoinableHandle::Action
405 * argument passed to the
406 * Thread::JoinableHandle::JoinableHandle(std::unique_ptr<Thread::Thread>,
407 * Action) constructor.
408 *
409 * Passing Thread::JoinableHandle::detach_on_exit to that argument is
410 * not always the correct choice where the thread callback has been
411 * bound to a reference argument in local scope and an exception might
412 * be thrown, because the thread will keep running after the
413 * Thread::JoinableHandle object and other local variables have
414 * (because of the exception) gone out of scope. Consider the
415 * following trivial parallelized calculation example:
416 *
417 * @code
418 * std::vector<int> get_readings();
419 * void get_mean(const std::vector<int>& v, int& result);
420 * void get_std_deviation(const std::vector<int>& v, int& result); // might throw
421 * void show_result(int mean, int deviation);
422 *
423 * using namespace Cgu;
424 * void do_calc() {
425 * int i, j;
426 * std::vector<int> v = get_readings();
427 * std::unique_ptr<Thread::Thread> t =
428 * Thread::Thread::start(std::bind(&get_mean, std::cref(v), std::ref(i)), true);
429 * if (t.get()) { // checks whether thread started correctly
430 * get_std_deviation(v, j);
431 * t->join();
432 * show_result(i, j);
433 * }
434 * }
435 * @endcode
436 *
437 * If get_std_deviation() throws, as well as there being a potential
438 * thread resource leak by virtue of no join being made, the thread
439 * executing get_mean() will continue running and attempt to access
440 * variable v, and put its result in variable i, which may by then
441 * both be out of scope. To deal with such a case, the thread could
442 * be wrapped in a Thread::JoinableHandle object which joins on exit
443 * rather than detaches, for example:
444 *
445 * @code
446 * ...
447 * using namespace Cgu;
448 * void do_calc() {
449 * int i, j;
450 * std::vector<int> v = get_readings();
451 * Thread::JoinableHandle t{Thread::Thread::start(std::bind(&get_mean, std::cref(v), std::ref(i)), true),
452 * Thread::JoinableHandle::join_on_exit};
453 * if (t.is_managing()) { // checks whether thread started correctly
454 * get_std_deviation(v, j);
455 * t.join();
456 * show_result(i, j);
457 * }
458 * }
459 * @endcode
460 *
461 * Better still, however, would be to use Cgu::Thread::Future in this
462 * kind of usage, namely a usage where a worker thread is intended to
463 * provide a result for inspection.
464 *
465 * @note These examples assume that the std::vector library
466 * implementation permits concurrent reads of a vector object by
467 * different threads. Whether that is the case depends on the
468 * documentation of the library concerned (if designed for a
469 * multi-threaded environment, most will permit this, and it is
470 * required for a fully conforming C++11 library implementation).
471 */
472 class JoinableHandle {
473 public:
474 enum Action {detach_on_exit, join_on_exit};
475
476 private:
477 Mutex mutex; // make this the first member so the constructors are strongly exception safe
478 Action action;
479 bool detached;
480 std::unique_ptr<Cgu::Thread::Thread> thread;
481
482 public:
483 /**
484 * Cancels the thread represented by the wrapped Thread::Thread
485 * object. It can be called by any thread. The effect is undefined
486 * if when called the thread represented by the wrapped Thread::Thread
487 * object has both (a) already terminated and (b) had a call to join()
488 * or detach() made for it. Accordingly, if the user is not able to
489 * establish from the program logic whether the thread has terminated,
490 * cancel() must not be called after a call to detach() has been made
491 * or a call to join() has returned: this can be ensured by only
492 * detaching or joining via this object's destructor (that is, by not
493 * using the explicit detach() and join() methods). This method does
494 * not throw.
495 * @note Use this method with care - see Thread::cancel() for further
496 * information.
497 */
498 void cancel();
499
500 /**
501 * Joins the thread represented by the wrapped Thread::Thread object
502 * (that is, waits for it to terminate), unless the detach() or join()
503 * method has previously been called in which case this call does
504 * nothing. It can be called by any thread other than the one
505 * represented by the wrapped Thread::Thread object, but only one
506 * thread can wait on it: if one thread (thread A) calls it while
507 * another thread (thread B) is already blocking on it, thread A's
508 * call to this method will return immediately and return false. It
509 * does not throw.
510 * @return true if a successful join() has been accomplished (that is,
511 * detach() or join() have not previously been called), otherwise
512 * false.
513 */
514 bool join();
515
516 /**
517 * Detaches the thread represented by this Thread::Thread object, so
518 * as to make it unjoinable, unless the detach() or join() method has
519 * previously been called in which case this call does nothing. It
520 * does not throw.
521 */
522 void detach();
523
524 /**
525 * Specifies whether the calling thread is the same thread as is
526 * represented by the wrapped Thread::Thread object. It can be called
527 * by any thread. The effect is undefined if the thread represented
528 * by the wrapped Thread::Thread object has both (a) already
529 * terminated and (b) had a call to join() or detach() made for it.
530 * Accordingly, if the user is not able to establish from the program
531 * logic whether the thread has terminated, is_caller() must not be
532 * called after a call to detach() has been made or a call to join()
533 * has returned: this can be ensured by only detaching or joining via
534 * this object's destructor (that is, by not using the explicit
535 * detach() and join() methods). This method does not throw.
536 * @return Returns true if the caller is in the thread represented by
537 * the wrapped Thread::Thread object. If not, or this JoinableHandle
538 * does not wrap any Thread object, then returns false.
539 */
540 bool is_caller();
541
542 /**
543 * Specifies whether this JoinableHandle object has been initialized
544 * with a Thread::Thread object representing a correctly started
545 * thread in respect of which neither JoinableHandle::detach() nor
546 * JoinableHandle::join() has been called. It can be called by any
547 * thread. It is principally intended to enable the constructor
548 * taking a std::unique_ptr<Cgu::Thread::Thread> object to be directly
549 * initialized by a call to Thread::Thread::start(), by providing a
550 * means for the thread calling Thread::Thread::start() to check
551 * afterwards that the new thread did, in fact, start correctly. Note
552 * that this method will return true even after the thread has
553 * finished, provided neither the join() nor detach() method has been
554 * called.
555 * @return Returns true if this object has been initialized by a
556 * Thread::Thread object representing a correctly started thread in
557 * respect of which neither JoinableHandle::detach() nor
558 * JoinableHandle::join() has been called, otherwise false.
559 */
560 bool is_managing();
561
562 /**
563 * Moves one JoinableHandle object to another JoinableHandle object.
564 * This is a move operation which transfers ownership to the assignee,
565 * as the handles store their Thread::Thread object by
566 * std::unique_ptr<>. Any existing thread managed by the assignee
567 * prior to the move will be detached if it has not already been
568 * detached or joined. This method will not throw.
569 * @param h The assignor/movant, which will cease to hold a valid
570 * Thread::Thread object after the move has taken place.
571 * @return A reference to the assignee JoinableHandle object after
572 * assignment.
573 * @note This method is thread safe as regards the assignee (the
574 * object assigned to), but no synchronization is carried out with
575 * respect to the rvalue assignor/movant. This is because temporaries
576 * are only visible and accessible in the thread carrying out the move
577 * operation and synchronization for them would represent pointless
578 * overhead. In a case where the user uses std::move to force a move
579 * from a named object, and that named object's lifetime is managed by
580 * (or the object is otherwise accessed by) a different thread than
581 * the one making the move, the user must carry out her own
582 * synchronization with respect to that different thread, as the named
583 * object will be mutated by the move.
584 */
585 JoinableHandle& operator=(JoinableHandle&& h);
586
587 /**
588 * This constructor initializes a new JoinableHandle object with a
589 * std::unique_ptr<Thread::Thread> object, as provided by
590 * Thread::Thread::start(). This is a move operation which transfers
591 * ownership to the new object.
592 * @param thr The initializing Thread::Thread object (which must have
593 * been created as joinable) passed by a std::unique_ptr smart
594 * pointer. This is a move operation.
595 * @param act Either Thread::JoinableHandle::detach_on_exit (which
596 * will cause the destructor to detach the thread if it has not
597 * previously been detached or joined) or
598 * Thread::JoinableHandle::join_on_exit (which will cause the
599 * destructor to join the thread if it has not previously been
600 * detached or joined).
601 * @exception Cgu::Thread::MutexError Throws this exception if
602 * initialization of the internal mutex fails. The constructor is
603 * strongly exception safe: if Cgu::Thread::MutexError is thrown, the
604 * initializing std::unique_ptr<Cgu::Thread::Thread> object will be
605 * left unchanged. (It is often not worth checking for this
606 * exception, as it means either memory is exhausted or pthread has
607 * run out of other resources to create new mutexes.)
608 * @note 1. It is not necessary to check that the thread parameter
609 * represents a correctly started thread (that is, that thr.get() does
610 * not return 0) before this constructor is invoked, because that can
611 * be done after construction by calling JoinableHandle::is_managing()
612 * (a JoinableHangle object can safely handle a case where thr.get()
613 * does return 0). This enables a JoinableHandle object to be
614 * directly initialized by this constructor from a call to
615 * Thread::Thread::start().
616 * @note 2. No synchronization is carried out with respect to the
617 * initializing std::unique_ptr object. This is because such an
618 * object is usually passed to this constructor as a temporary, which
619 * is only visible and accessible in the thread carrying out the move
620 * operation, in which case synchronization would represent pointless
621 * overhead. In a case where the user uses std::move to force a move
622 * from a named std::unique_ptr object, and that named object's
623 * lifetime is managed by (or the object is otherwise accessed by) a
624 * different thread than the one making the move, the user must carry
625 * out her own synchronization with respect to that different thread,
626 * as the initializing std::unique_ptr object will be mutated by the
627 * move.
628 * @sa JoinableHandle::is_managing().
629 */
630 JoinableHandle(std::unique_ptr<Cgu::Thread::Thread> thr, Action act): action(act), detached(false), thread(std::move(thr)) {}
631
632 /**
633 * This constructor initializes a new JoinableHandle object with an
634 * existing JoinableHandle object. This is a move operation which
635 * transfers ownership to the new object.
636 * @param h The initializing JoinableHandle object, which will cease
637 * to hold a valid Thread::Thread object after the initialization has
638 * taken place.
639 * @exception Cgu::Thread::MutexError Throws this exception if
640 * initialization of the internal mutex fails. The constructor is
641 * strongly exception safe: if Cgu::Thread::MutexError is thrown, the
642 * initializing Cgu::Thread::JoinableHandle object will be left
643 * unchanged. (It is often not worth checking for this exception, as
644 * it means either memory is exhausted or pthread has run out of other
645 * resources to create new mutexes.)
646 * @note No synchronization is carried out with respect to the
647 * initializing rvalue. This is because temporaries are only visible
648 * and accessible in the thread carrying out the move operation and
649 * synchronization for them would represent pointless overhead. In a
650 * case where a user uses std::move to force a move from a named
651 * object, and that named object's lifetime is managed by (or the
652 * object is otherwise accessed by) a different thread than the one
653 * making the move, the user must carry out her own synchronization
654 * with respect to that different thread, as the named object will be
655 * mutated by the move.
656 */
657 JoinableHandle(JoinableHandle&& h): action(h.action), detached(h.detached), thread(std::move(h.thread)) {}
658
659 /**
660 * The default constructor. Nothing is managed until the move
661 * assignment operator has been called.
662 * @exception Cgu::Thread::MutexError Throws this exception if
663 * initialization of the internal mutex fails. (It is often not worth
664 * checking for this exception, as it means either memory is exhausted
665 * or pthread has run out of other resources to create new mutexes.)
666 *
667 * Since 2.0.8
668 */
669 JoinableHandle(): action(detach_on_exit), detached(true) {}
670
671 /**
672 * The destructor will detach a managed thread (if the
673 * Thread::JoinableHandle::detach_on_exit flag is set) or join it (if
674 * the Thread::JoinableHandle::join_on_exit flag is set), unless it
675 * has previously been detached or joined with the detach() or join()
676 * methods. The destructor is thread safe (any thread may destroy the
677 * JoinableHandle object). The destructor will not throw.
678 */
679 ~JoinableHandle();
680
681 /* Only has effect if --with-glib-memory-slices-compat or
682 * --with-glib-memory-slices-no-compat option picked */
683 CGU_GLIB_MEMORY_SLICES_FUNCS
684 };
685
686 /**
687 * @class CancelBlock thread.h c++-gtk-utils/thread.h
688 * @brief A class enabling the cancellation state of a thread to be
689 * controlled.
690 *
691 * A class enabling the cancellation state of a thread to be
692 * controlled, so as to provide exception safe cancellation state
693 * changes. When a CancelBlock object goes out of scope, the thread's
694 * cancellation state is returned to the state it was in immediately
695 * prior to the object's construction.
696 *
697 * Cancellation state can be changed before a CancelBlock object goes
698 * out of scope by calling its block() and unblock() methods.
699 * However, care should be taken if calling unblock() for the purpose
700 * of enabling thread cancellation while the CancelBlock object is
701 * still in existence: this should normally only be done if the
702 * thread's cancellation state at the time the CancelBlock object was
703 * constructed (which is the cancellation state to which the thread
704 * will be restored when the object goes out of scope) was
705 * PTHREAD_CANCEL_DISABLE. This is because when a thread begins
706 * cancellation the POSIX standard states that it will automatically
707 * switch itself into a PTHREAD_CANCEL_DISABLE state (see System
708 * Interfaces, section 2.9.5, Thread Cancellation Cleanup Handlers),
709 * and the POSIX standard further states that the behaviour is
710 * undefined if a cancellation handler attempts to enable cancellation
711 * again while the thread is cleaning up - and any thread
712 * implementation such as NPTL which unwinds the stack on cancellation
713 * will do so if the CancelBlock's destructor would restore to
714 * PTHREAD_CANCEL_ENABLE state. Whilst it is to be expected that any
715 * cancellation stack unwinding implementation will behave sensibly in
716 * these circumstances, this is not mandated by POSIX, so making code
717 * relying on this less portable.
718 *
719 * For these reasons, the same care should be exercised if passing
720 * 'false' to the CancelBlock constructor's 'blocking' argument.
721 */
722
723 class CancelBlock {
724 int starting_state;
725 public:
726 /**
727 * This class cannot be copied. The copy constructor is deleted.
728 */
729 CancelBlock(const CancelBlock&) = delete;
730
731 /**
732 * This class cannot be copied. The assignment operator is deleted.
733 */
734 CancelBlock& operator=(const CancelBlock&) = delete;
735
736 /**
737 * Makes the thread uncancellable, even if the code passes through a
738 * cancellation point, while the CancelBlock object exists (when the
739 * CancelBlock object ceases to exist, cancellation state is returned
740 * to the state prior to it being constructed). It should only be
741 * called by the thread which created the CancelBlock object. This
742 * method will not throw.
743 * @param old_state Indicates the cancellation state of the calling
744 * thread immediately before this call to block() was made, either
745 * PTHREAD_CANCEL_ENABLE (if the thread was previously cancellable) or
746 * PTHREAD_CANCEL_DISABLE (if this call did nothing because the thread
747 * was already uncancellable).
748 * @return 0 if successful, else a value other than 0.
749 */
750 static int block(int& old_state) noexcept {return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);}
751
752 /**
753 * Makes the thread uncancellable, even if the code passes through a
754 * cancellation point, while the CancelBlock object exists (when the
755 * CancelBlock object ceases to exist, cancellation state is returned
756 * to the state prior to it being constructed). It should only be
757 * called by the thread which created the CancelBlock object. This
758 * method will not throw.
759 * @return 0 if successful, else a value other than 0.
760 */
761 static int block() noexcept {int old_state; return block(old_state);}
762
763 /**
764 * Makes the thread cancellable while the CancelBlock object exists
765 * (when the CancelBlock object ceases to exist, cancellation state is
766 * returned to the state prior to it being constructed). It should
767 * only be called by the thread which created the CancelBlock object.
768 * This method will not throw. The 'Detailed Description' section
769 * above has information about the issues to be taken into account if
770 * a call to this method is to be made.
771 * @param old_state Indicates the cancellation state of the calling
772 * thread immediately before this call to unblock() was made, either
773 * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable)
774 * or PTHREAD_CANCEL_ENABLE (if this call did nothing because the
775 * thread was already cancellable).
776 * @return 0 if successful, else a value other than 0.
777 */
778 static int unblock(int& old_state) noexcept {return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);}
779
780 /**
781 * Makes the thread cancellable while the CancelBlock object exists
782 * (when the CancelBlock object ceases to exist, cancellation state is
783 * returned to the state prior to it being constructed). It should
784 * only be called by the thread which created the CancelBlock object.
785 * This method will not throw. The 'Detailed Description' section
786 * above has information about the issues to be taken into account if
787 * a call to this method is to be made.
788 * @return 0 if successful, else a value other than 0.
789 */
790 static int unblock() noexcept {int old_state; return unblock(old_state);}
791
792 /**
793 * Restores cancellation state to the state it was in immediately
794 * before this CancelBlock object was constructed. It should only be
795 * called by the thread which created the CancelBlock object. This
796 * method will not throw.
797 * @param old_state Indicates the cancellation state of the calling
798 * thread immediately before this call to restore() was made, either
799 * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable)
800 * or PTHREAD_CANCEL_ENABLE (if this thread was previously
801 * cancellable).
802 * @return 0 if successful, else a value other than 0.
803 */
804 int restore(int& old_state) noexcept {return pthread_setcancelstate(starting_state, &old_state);}
805
806 /**
807 * Restores cancellation state to the state it was in immediately
808 * before this CancelBlock object was constructed. It should only be
809 * called by the thread which created the CancelBlock object. This
810 * method will not throw.
811 * @return 0 if successful, else a value other than 0.
812 */
813 int restore() noexcept {int old_state; return restore(old_state);}
814
815 /**
816 * The constructor will not throw.
817 * @param blocking Whether the CancelBlock object should start in
818 * blocking mode. The 'Detailed Description' section above has
819 * information about the issues to be taken into account if 'false' is
820 * passed to this parameter.
821 */
822 CancelBlock(bool blocking = true);
823
824 /**
825 * The destructor will put the thread in the cancellation state that
826 * it was in immediately before the CancelBlock object was constructed
827 * (which might be blocking). It will not throw.
828 */
829 ~CancelBlock() {restore();}
830
831 /* Only has effect if --with-glib-memory-slices-compat or
832 * --with-glib-memory-slices-no-compat option picked */
833 CGU_GLIB_MEMORY_SLICES_FUNCS
834 };
835
836 /**
837 * @class Exit thread.h c++-gtk-utils/thread.h
838 * @brief A class which can be thrown to terminate the throwing
839 * thread.
840 *
841 * This class can be thrown (instead of calling pthread_exit()) when a
842 * thread wishes to terminate itself and also ensure stack unwinding,
843 * so that destructors of local objects are called. It is caught
844 * automatically by the implementation of Cgu::Thread::Thread::start()
845 * so that it will only terminate the thread throwing it and not the
846 * whole process. See the Cgu::Thread::Thread::cancel() method above,
847 * for use when a thread wishes to terminate another one, and the
848 * caveats on the use of Cgu::Thread::Thread::cancel().
849 *
850 * Do not throw a Cgu::Thread::Exit object in a program with more than
851 * one main loop in order to terminate one of the threads which has
852 * its own main loop. Instead, just cause its main loop to terminate
853 * by, say, calling g_main_loop_quit() on it.
854 */
855 class Exit {};
856
857 } // namespace Thread
858
859 } // namespace Cgu
860
861 #endif
Cgu::Thread::JoinableHandle::cancel
void cancel()
Cgu::Callback::CallbackArg
The callback interface class.
Definition: callback.h:567
Cgu::Thread::Thread::cancel
void cancel() noexcept
Definition: thread.h:215
Cgu
Definition: application.h:44
Cgu::Thread::JoinableHandle
A class wrapping a Thread::Thread object representing a joinable thread.
Definition: thread.h:472
Cgu::Thread::CancelBlock::block
static int block() noexcept
Definition: thread.h:761
Cgu::Thread::Thread::detach
void detach() noexcept
Definition: thread.h:236
Cgu::Thread::JoinableHandle::join_on_exit
@ join_on_exit
Definition: thread.h:474
Cgu::Thread::CancelBlock::operator=
CancelBlock & operator=(const CancelBlock &)=delete
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle()
Definition: thread.h:669
Cgu::Thread::CancelBlock::~CancelBlock
~CancelBlock()
Definition: thread.h:829
Cgu::Thread::CancelBlock::CancelBlock
CancelBlock(const CancelBlock &)=delete
Cgu::Thread::Thread::is_caller
bool is_caller() noexcept
Definition: thread.h:252
Cgu::Thread::Thread::join
void join() noexcept
Definition: thread.h:227
callback.h
This file provides classes for type erasure.
Cgu::Thread::JoinableHandle::Action
Action
Definition: thread.h:474
Cgu::Thread::Exit
A class which can be thrown to terminate the throwing thread.
Definition: thread.h:855
Cgu::Thread::CancelBlock::restore
int restore(int &old_state) noexcept
Definition: thread.h:804
Cgu::Thread::JoinableHandle::~JoinableHandle
~JoinableHandle()
Cgu::Thread::JoinableHandle::is_caller
bool is_caller()
Cgu::Thread::JoinableHandle::detach
void detach()
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle(JoinableHandle &&h)
Definition: thread.h:657
Cgu::Thread::JoinableHandle::is_managing
bool is_managing()
Cgu::Thread::JoinableHandle::join
bool join()
Cgu::Thread::Thread::operator=
Thread & operator=(const Thread &)=delete
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Cgu::Thread::JoinableHandle::detach_on_exit
@ detach_on_exit
Definition: thread.h:474
Cgu::Thread::CancelBlock
A class enabling the cancellation state of a thread to be controlled.
Definition: thread.h:723
mutex.h
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Cgu::Thread::JoinableHandle::operator=
JoinableHandle & operator=(JoinableHandle &&h)
Cgu::Thread::CancelBlock::unblock
static int unblock() noexcept
Definition: thread.h:790
Cgu::Thread::CancelBlock::unblock
static int unblock(int &old_state) noexcept
Definition: thread.h:778
Cgu::Thread::CancelBlock::restore
int restore() noexcept
Definition: thread.h:813
Cgu::Thread::Thread::start
static std::unique_ptr< Cgu::Thread::Thread > start(F &&func, bool joinable)
Definition: thread.h:379
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:117
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle(std::unique_ptr< Cgu::Thread::Thread > thr, Action act)
Definition: thread.h:630
Cgu::Thread::Thread
A class representing a pthread thread.
Definition: thread.h:166
Cgu::Thread::CancelBlock::block
static int block(int &old_state) noexcept
Definition: thread.h:750
cgu_config.h
Cgu::Thread::Thread::start
static std::unique_ptr< Cgu::Thread::Thread > start(const Cgu::Callback::Callback *cb, bool joinable)