c++-gtk-utils
thread.h
Go to the documentation of this file.
1 /* Copyright (C) 2005 to 2014 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>
29 
30 #include <pthread.h>
31 
32 #include <c++-gtk-utils/callback.h>
33 #include <c++-gtk-utils/mutex.h>
35 
36 namespace Cgu {
37 
38 namespace Thread {
39 
40 /**
41  * @class Cgu::Thread::Thread thread.h c++-gtk-utils/thread.h
42  * @brief A class representing a pthread thread.
43  * @sa Thread::Mutex Thread::Mutex::Lock Thread::Cond Thread::Future Thread::JoinableHandle
44  *
45  * The Thread class encapsulates a pthread thread. It can start, join
46  * and cancel a thread.
47  *
48  * @note The Thread class, and the other thread related classes
49  * provided by this library such as Mutex, RecMutex, RWLock,
50  * CancelBlock and Cond, can be used interchangeably with (and mixed
51  * with) GThread objects and functions, and with GMutex, GRecMutex,
52  * GRWLock, GCond and similar, as they all use pthreads underneath on
53  * POSIX and other unix-like OSes. The main feature available with
54  * this thread implementation and not GThreads is thread cancellation,
55  * the mutex scoped locking classes Thread::Mutex::Lock and
56  * Thread::RecMutex::Lock, the joinable thread scoped management class
57  * Thread::JoinableHandle and the Thread::Future class (abstracting
58  * thread functions which provide a result). There is no need from
59  * the perspective of this class to call g_thread_init() before
60  * Cgu::Thread::Thread::start() is called, but prior to glib version
61  * 2.32 glib itself is not thread-safe without g_thread_init(), so
62  * where this class is used with glib < 2.32, g_thread_init() should
63  * be called at program initialization.
64  *
65  * See @ref Threading for particulars about GTK+ thread safety.
66  */
67 
68 
69 class Thread {
70  pthread_t thread;
71  // private constructor - this class can only be created with Thread::start
72  Thread() {}
73  // and it cannot be copied - this class has single ownership semantics
74  Thread(const Thread&);
75  Thread& operator=(const Thread&);
76 public:
77 
78 /**
79  * Cancels the thread represented by this Thread object. It can be
80  * called by any thread. The effect is undefined if the thread
81  * represented by this Thread object has both (a) already terminated
82  * and (b) been detached or had a call to join() made for it.
83  * Accordingly, if the user is not able to establish from the program
84  * logic whether the thread has terminated, the thread must be created
85  * as joinable and cancel() must not be called after a call to
86  * detach() has been made or a call to join() has returned. A
87  * Thread::JoinableHandle object can used to ensure this. It does not
88  * throw.
89  * @note 1. Use this method with care - sometimes its use is
90  * unavoidable but destructors for local objects may not be called if
91  * a thread exits by virtue of a call to cancel() (that depends on the
92  * implementation). Most modern commercial unixes, and recent
93  * linux/BSD distributions based on NPTL, will unwind the stack and
94  * call destructors on thread cancellation by means of a
95  * pseudo-exception, but older distributions relying on the former
96  * linuxthreads implementation will not. Therefore for maximum
97  * portability only have plain data structures/built-in types in
98  * existence in local scope when it occurs and if there is anything in
99  * free store to be released implement clean-ups with
100  * pthread_cleanup_push()/pthread_cleanup_pop(). This should be
101  * controlled with pthread_setcancelstate() and/or the CancelBlock
102  * class to choose the cancellation point.
103  * @note 2. When using thread cancellation, do not allow a
104  * cancellation pseudo-exception to propagate through a function with
105  * an exception specification, as the cancellation pseudo-exception
106  * may be incompatible with the specification and std::unexpected may
107  * be called.
108  * @sa Cgu::Thread::Exit
109  */
110  void cancel() {pthread_cancel(thread);}
111 
112 /**
113  * Joins the thread represented by this Thread object (that is, waits
114  * for it to terminate). It can only be called by one thread, which
115  * can be any thread other than the one represented by this Thread
116  * object. The result is undefined if the thread represented by this
117  * Thread object is or was detached or join() has already been called
118  * for it (a Thread::JoinableHandle object will however give a defined
119  * result in such cases for threads originally started as joinable).
120  * It does not throw.
121  */
122  void join() {pthread_join(thread, 0);}
123 
124 /**
125  * Detaches the thread represented by this Thread object where it is
126  * joinable, so as to make it unjoinable. The effect is undefined if
127  * the thread is already unjoinable (a Thread::JoinableHandle object
128  * will however give a defined result in such cases for threads
129  * originally started as joinable). It does not throw.
130  */
131  void detach() {pthread_detach(thread);}
132 
133 /**
134  * Specifies whether the calling thread is the same thread as is
135  * represented by this Thread object. The effect is undefined if the
136  * thread represented by this Thread object has both (a) already
137  * terminated and (b) been detached or had a call to join() made for
138  * it. Accordingly, if the user is not able to establish from the
139  * program logic whether the thread has terminated, the thread must be
140  * created as joinable and is_caller() must not be called after a call
141  * to detach() has been made or a call to join() has returned. A
142  * Thread::JoinableHandle object can used to ensure this. This method
143  * does not throw.
144  * @return Returns true if the caller is in the thread represented by
145  * this Thread object.
146  */
147  bool is_caller() {return pthread_equal(thread, pthread_self());}
148 
149 /**
150  * Starts a new thread. It can be called by any thread.
151  * @param cb A callback object (created by Callback::make() or
152  * Callback::make_ref()) encapsulating the function to be executed by
153  * the new thread. The Thread object returned by this function will
154  * take ownership of the callback: it will automatically be deleted
155  * either by the new thread when it has finished with it, or by this
156  * method in the calling thread if the attempt to start a new thread
157  * fails (including if std::bad_alloc is thrown).
158  * @param joinable Whether the join() method may be called in relation
159  * to the new thread.
160  * @return A Thread object representing the new thread which has been
161  * started, held by a std::auto_ptr object as it has single ownership
162  * semantics. The std::auto_ptr object will be empty (that is
163  * std::auto_ptr<Cgu::Thread::Thread>::get() will return 0) if the
164  * thread did not start correctly, which would mean that memory is
165  * exhausted, the pthread thread limit has been reached or pthread has
166  * run out of other resources to start new threads.
167  * @exception std::bad_alloc This method might throw std::bad_alloc if
168  * memory is exhausted and the system throws in that case. (This
169  * exception will not be thrown if the library has been installed
170  * using the \--with-glib-memory-slices-no-compat configuration
171  * option: instead glib will terminate the program if it is unable to
172  * obtain memory from the operating system.) If this exception is
173  * thrown, the thread will not have started.
174  * @note 1. The thread will keep running even if the return value of
175  * start() goes out of scope (but it will no longer be possible to
176  * call any of the methods in this class for it, which is fine if the
177  * thread is not started as joinable and it is not intended to cancel
178  * it).
179  * @note 2. If the thread is started with the joinable attribute, the
180  * user must subsequently either call the join() or the detach()
181  * method, as otherwise a resource leak may occur (the destructor of
182  * this class does not call detach() automatically). Alternatively,
183  * the return value of this method can be passed to a
184  * Thread::JoinableHandle object which will do this automatically in
185  * the Thread::JoinableHandle object's destructor.
186  * @note 3. Any Thread::Exit exception thrown from the function
187  * executed by the new thread will be caught and consumed. The thread
188  * will safely terminate and unwind the stack in so doing.
189  * @note 4. If any uncaught exception other than Thread::Exit is
190  * allowed to propagate from the initial function executed by the new
191  * thread, the exception is not consumed (NPTL's forced stack
192  * unwinding on cancellation does not permit catching with an ellipsis
193  * argument without rethrowing, and even if it did permit it, the
194  * result would be an unreported error). Neither POSIX nor the
195  * C++98/03 standard specifies what is to happen in that case. In
196  * practice, most implementations will call std::terminate() and so
197  * terminate the entire program, and this behaviour is required where
198  * the program is compiled under C++11. Accordingly, a user must make
199  * sure that no exceptions, other than Thread::Exit or any
200  * cancellation pseudo-exception, can propagate from the initial
201  * function executed by the new thread. This includes ensuring that,
202  * for any argument passed to that function which is not a built-in
203  * type and which is not taken by the function by const or non-const
204  * reference, the argument type's copy constructor does not throw.
205  */
206  static std::auto_ptr<Cgu::Thread::Thread> start(const Cgu::Callback::Callback* cb,
207  bool joinable);
208 
209 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
211 #endif
212 };
213 
214 /**
215  * @class Cgu::Thread::JoinableHandle thread.h c++-gtk-utils/thread.h
216  * @brief A class wrapping a Thread::Thread object representing a
217  * joinable thread.
218  * @sa Thread::Thread Thread::Future
219  *
220  * This class enables a joinable thread to be made more easily
221  * exception safe. It can also be used to provide that a joinable
222  * thread is not detached or joined while other methods dependent on
223  * that might still be called, and to provide a defined result where
224  * there are multiple calls to join() and/or detach(). When it is
225  * destroyed, it will either detach or join the thread represented by
226  * the wrapped Thread::Thread object unless it has previously been
227  * detached or joined using the detach() or join() methods, so
228  * avoiding thread resource leaks. Whether it will detach() or join()
229  * on destruction depends on the Thread::JoinableHandle::Action
230  * argument passed to the
231  * Thread::JoinableHandle::JoinableHandle(std::auto_ptr<Thread::Thread>,
232  * Action) constructor.
233  *
234  * Passing Thread::JoinableHandle::detach_on_exit to that argument is
235  * not always the correct choice where the thread callback has been
236  * bound to a reference argument in local scope and an exception might
237  * be thrown, because the thread will keep running after the
238  * Thread::JoinableHandle object and other local variables have
239  * (because of the exception) gone out of scope. Consider the
240  * following trivial parallelized calculation example:
241  *
242  * @code
243  * std::vector<int> get_readings();
244  * void get_mean(const std::vector<int>& v, int& result);
245  * void get_std_deviation(const std::vector<int>& v, int& result); // might throw
246  * void show_result(int mean, int deviation);
247  *
248  * using namespace Cgu;
249  * void do_calc() {
250  * int i, j;
251  * std::vector<int> v = get_readings();
252  * // with bound reference arguments, Callback::make() requires explicit type instantation
253  * std::auto_ptr<Thread::Thread> t =
254  * Thread::Thread::start(Callback::make<const std::vector<int>&, int&>(&get_mean, v, i), true);
255  * if (t.get()) { // checks whether thread started correctly
256  * get_std_deviation(v, j);
257  * t->join();
258  * show_result(i, j);
259  * }
260  * }
261  * @endcode
262  *
263  * If get_std_deviation() throws, as well as there being a potential
264  * thread resource leak by virtue of no join being made, the thread
265  * executing get_mean() will continue running and attempt to access
266  * variable v, and put its result in variable i, which may by then
267  * both be out of scope. To deal with such a case, the thread could
268  * be wrapped in a Thread::JoinableHandle object which joins on exit
269  * rather than detaches, for example:
270  *
271  * @code
272  * ...
273  * using namespace Cgu;
274  * void do_calc() {
275  * int i, j;
276  * std::vector<int> v = get_readings();
277  * // with reference arguments, Callback::make() requires explicit type instantation
278  * Thread::JoinableHandle t(Thread::Thread::start(Callback::make<const std::vector<int>&, int&>(&get_mean, v, i), true),
279  * Thread::JoinableHandle::join_on_exit);
280  * if (t.is_managing()) { // checks whether thread started correctly
281  * get_std_deviation(v, j);
282  * t.join();
283  * show_result(i, j);
284  * }
285  * }
286  * @endcode
287  *
288  * Better still, however, would be to use Cgu::Thread::Future in this
289  * kind of usage, namely a usage where a worker thread is intended to
290  * provide a result for inspection.
291  *
292  * @note These examples assume that the std::vector library
293  * implementation permits concurrent reads of a vector object by
294  * different threads. Whether that is the case depends on the
295  * documentation of the library concerned (if designed for a
296  * multi-threaded environment, most will permit this).
297  */
299 public:
301 
302 private:
303  Mutex mutex; // make this the first member so the constructors are strongly exception safe
304  Action action;
305  bool detached;
306  std::auto_ptr<Cgu::Thread::Thread> thread_a;
307 
308 public:
309 /**
310  * Cancels the thread represented by the wrapped Thread::Thread
311  * object. It can be called by any thread. The effect is undefined
312  * if when called the thread represented by the wrapped Thread::Thread
313  * object has both (a) already terminated and (b) had a call to join()
314  * or detach() made for it. Accordingly, if the user is not able to
315  * establish from the program logic whether the thread has terminated,
316  * cancel() must not be called after a call to detach() has been made
317  * or a call to join() has returned: this can be ensured by only
318  * detaching or joining via this object's destructor (that is, by not
319  * using the explicit detach() and join() methods). This method does
320  * not throw.
321  * @note Use this method with great care - see Thread::cancel() for
322  * further information.
323  *
324  * Since 1.0.2
325  */
326  void cancel();
327 
328 /**
329  * Joins the thread represented by the wrapped Thread::Thread object
330  * (that is, waits for it to terminate), unless the detach() or join()
331  * method has previously been called in which case this call does
332  * nothing. It can be called by any thread other than the one
333  * represented by the wrapped Thread::Thread object, but only one
334  * thread can wait on it: if one thread (thread A) calls it while
335  * another thread (thread B) is already blocking on it, thread A's
336  * call to this method will return immediately and return false. It
337  * does not throw.
338  * @return true if a successful join() has been accomplished (that is,
339  * detach() or join() have not previously been called), otherwise
340  * false.
341  *
342  * Since 1.0.2
343  */
344  bool join();
345 
346 /**
347  * Detaches the thread represented by this Thread::Thread object, so
348  * as to make it unjoinable, unless the detach() or join() method has
349  * previously been called in which case this call does nothing. It
350  * does not throw.
351  *
352  * Since 1.0.2
353  */
354  void detach();
355 
356 /**
357  * Specifies whether the calling thread is the same thread as is
358  * represented by the wrapped Thread::Thread object. It can be called
359  * by any thread. The effect is undefined if the thread represented
360  * by the wrapped Thread::Thread object has both (a) already
361  * terminated and (b) had a call to join() or detach() made for it.
362  * Accordingly, if the user is not able to establish from the program
363  * logic whether the thread has terminated, is_caller() must not be
364  * called after a call to detach() has been made or a call to join()
365  * has returned: this can be ensured by only detaching or joining via
366  * this object's destructor (that is, by not using the explicit
367  * detach() and join() methods). This method does not throw.
368  * @return Returns true if the caller is in the thread represented by
369  * the wrapped Thread::Thread object. If not, or this JoinableHandle
370  * does not wrap any Thread object, then returns false.
371  *
372  * Since 1.0.2
373  */
374  bool is_caller();
375 
376 /**
377  * Specifies whether this JoinableHandle object has been initialized
378  * with a Thread::Thread object representing a correctly started
379  * thread in respect of which neither JoinableHandle::detach() nor
380  * JoinableHandle::join() has been called. It can be called by any
381  * thread. It is principally intended to enable the constructor
382  * taking a std::auto_ptr<Cgu::Thread::Thread> object to be directly
383  * initialized by a call to Thread::Thread::start(), by providing a
384  * means for the thread calling Thread::Thread::start() to check
385  * afterwards that the new thread did, in fact, start correctly. Note
386  * that this method will return true even after the thread has
387  * finished, provided neither the join() nor detach() method has been
388  * called.
389  * @return Returns true if this object has been initialized by a
390  * Thread::Thread object representing a correctly started thread in
391  * respect of which neither JoinableHandle::detach() nor
392  * JoinableHandle::join() has been called, otherwise false.
393  *
394  * Since 1.2.0
395  */
396  bool is_managing();
397 
398 /**
399  * Moves one JoinableHandle object to another JoinableHandle object.
400  * This is a move operation which transfers ownership to the assignee,
401  * as the handles store their Thread::Thread object by
402  * std::auto_ptr<>. Any existing thread managed by the assignee prior
403  * to the move will be detached if it has not already been detached or
404  * joined. This method will not throw.
405  * @param h The assignor/movant, which will cease to hold a valid
406  * Thread::Thread object after the move has taken place.
407  * @return A reference to the assignee JoinableHandle object after
408  * assignment.
409  * @note This method is thread safe as regards the assignee (the
410  * object assigned to), but no synchronization is carried out with
411  * respect to the assignor/movant. This is because, if a move
412  * operation is carried out from a JoinableHandle object which happens
413  * to have its lifetime managed by (or which is otherwise accessed by)
414  * a different thread than the one making the move, the user will
415  * normally need to carry out her own additional synchronization
416  * anyway to ensure that the object to be moved from still exists and
417  * is in the state required by the program. The user should ensure
418  * that the additional synchronization with respect to any such
419  * different thread also deals with the consequences of the move
420  * carried out by this method, as the assignor/movant will be mutated
421  * by the move.
422  *
423  * Since 1.0.2
424  */
426 
427 /**
428  * This constructor initializes a new JoinableHandle object with a
429  * std::auto_ptr<Thread::Thread> object, as provided by
430  * Thread::Thread::start(). This is a move operation which transfers
431  * ownership to the new object.
432  * @param thread The initializing Thread::Thread object (which must
433  * have been created as joinable) passed by a std::auto_ptr smart
434  * pointer. The std::auto_ptr smart pointer will cease to hold a
435  * valid Thread::Thread object after the initialization has taken
436  * place.
437  * @param act Either Thread::JoinableHandle::detach_on_exit (which
438  * will cause the destructor to detach the thread if it has not
439  * previously been detached or joined) or
440  * Thread::JoinableHandle::join_on_exit (which will cause the
441  * destructor to join the thread if it has not previously been
442  * detached or joined).
443  * @exception Cgu::Thread::MutexError Throws this exception if
444  * initialization of the internal mutex fails. The constructor is
445  * strongly exception safe: if Cgu::Thread::MutexError is thrown, the
446  * initializing std::auto_ptr<Cgu::Thread::Thread> object will be left
447  * unchanged. (It is often not worth checking for this exception, as
448  * it means either memory is exhausted or pthread has run out of other
449  * resources to create new mutexes.)
450  * @note 1. It is not necessary to check that the thread parameter
451  * represents a correctly started thread (that is, that thread.get()
452  * does not return 0) before this constructor is invoked, because that
453  * can be done after construction by calling
454  * JoinableHandle::is_managing() (a JoinableHangle object can safely
455  * handle a case where thread.get() does return 0). This enables a
456  * JoinableHandle object to be directly initialized by this
457  * constructor from a call to Thread::Thread::start().
458  * @note 2. No synchronization is carried out with respect to the
459  * initializing std::auto_ptr object. This is because such an object
460  * is usually passed to this constructor as a temporary, which is only
461  * visible and accessible in the thread carrying out the move
462  * operation, in which case synchronization would represent pointless
463  * overhead. Where the std::auto_ptr object from which the move is
464  * carried out is a named object which happens to have its lifetime
465  * managed by (or is otherwise accessed by) a different thread than
466  * the one making the move, the user will need to carry out her own
467  * synchronization, as the initializing std::auto_ptr object will be
468  * mutated by the move.
469  * @sa JoinableHandle::is_managing().
470  *
471  * Since 1.0.2
472  */
473  JoinableHandle(std::auto_ptr<Cgu::Thread::Thread> thread, Action act): action(act), detached(false), thread_a(thread) {}
474 
475 /**
476  * This constructor initializes a new JoinableHandle object with an
477  * existing JoinableHandle object. This is a move operation which
478  * transfers ownership to the new object.
479  * @param h The initializing JoinableHandle object, which will cease
480  * to hold a valid Thread::Thread object after the initialization has
481  * taken place.
482  * @exception Cgu::Thread::MutexError Throws this exception if
483  * initialization of the internal mutex fails. The constructor is
484  * strongly exception safe: if Cgu::Thread::MutexError is thrown, the
485  * initializing Cgu::Thread::JoinableHandle object will be left
486  * unchanged. (It is often not worth checking for this exception, as
487  * it means either memory is exhausted or pthread has run out of other
488  * resources to create new mutexes.)
489  * @note No synchronization is carried out with respect to the
490  * initializing object. This is because, if a move operation is
491  * carried out from a JoinableHandle object which happens to have its
492  * lifetime managed by (or which is otherwise accessed by) a different
493  * thread than the one making the move, the user will normally need to
494  * carry out her own synchronization anyway to ensure that the object
495  * to be moved from still exists and is in the state required by the
496  * program. The user should ensure that the synchronization with
497  * respect to any such different thread also deals with the
498  * consequences of the move carried out by this constructor, as the
499  * initializing object will be mutated by the move.
500  *
501  * Since 1.0.2
502  */
503  JoinableHandle(JoinableHandle& h): action(h.action), detached(h.detached), thread_a(h.thread_a) {}
504 
505 /**
506  * The default constructor. Nothing is managed until the assignment
507  * operator has been called.
508  * @exception Cgu::Thread::MutexError Throws this exception if
509  * initialization of the internal mutex fails. (It is often not worth
510  * checking for this exception, as it means either memory is exhausted
511  * or pthread has run out of other resources to create new mutexes.)
512  *
513  * Since 1.2.22
514  */
515  JoinableHandle(): action(detach_on_exit), detached(true) {}
516 
517 /**
518  * The destructor will detach a managed thread (if the
519  * Thread::JoinableHandle::detach_on_exit flag is set) or join it (if
520  * the Thread::JoinableHandle::join_on_exit flag is set), unless it
521  * has previously been detached or joined with the detach() or join()
522  * methods. The destructor is thread safe (any thread may destroy the
523  * JoinableHandle object). The destructor will not throw.
524  *
525  * Since 1.0.2
526  */
528 
529 /* Only has effect if --with-glib-memory-slices-compat or
530  * --with-glib-memory-slices-no-compat option picked */
532 };
533 
534 /**
535  * @class CancelBlock thread.h c++-gtk-utils/thread.h
536  * @brief A class enabling the cancellation state of a thread to be
537  * controlled.
538  *
539  * A class enabling the cancellation state of a thread to be
540  * controlled, so as to provide exception safe cancellation state
541  * changes. When a CancelBlock object goes out of scope, the thread's
542  * cancellation state is returned to the state it was in immediately
543  * prior to the object's construction.
544  *
545  * Cancellation state can be changed before a CancelBlock object goes
546  * out of scope by calling its block() and unblock() methods.
547  * However, care should be taken if calling unblock() for the purpose
548  * of enabling thread cancellation while the CancelBlock object is
549  * still in existence: this should normally only be done if the
550  * thread's cancellation state at the time the CancelBlock object was
551  * constructed (which is the cancellation state to which the thread
552  * will be restored when the object goes out of scope) was
553  * PTHREAD_CANCEL_DISABLE. This is because when a thread begins
554  * cancellation the POSIX standard states that it will automatically
555  * switch itself into a PTHREAD_CANCEL_DISABLE state (see System
556  * Interfaces, section 2.9.5, Thread Cancellation Cleanup Handlers),
557  * and the POSIX standard further states that the behaviour is
558  * undefined if a cancellation handler attempts to enable cancellation
559  * again while the thread is cleaning up - and any thread
560  * implementation such as NPTL which unwinds the stack on cancellation
561  * will do so if the CancelBlock's destructor would restore to
562  * PTHREAD_CANCEL_ENABLE state. Whilst it is to be expected that any
563  * cancellation stack unwinding implementation will behave sensibly in
564  * these circumstances, this is not mandated by POSIX, so making code
565  * relying on this less portable.
566  *
567  * For these reasons, the same care should be exercised if passing
568  * 'false' to the CancelBlock constructor's 'blocking' argument.
569  */
570 
571 class CancelBlock {
572  int starting_state;
573 
574  // CancelBlocks cannot be copied
575  CancelBlock(const CancelBlock&);
576  CancelBlock& operator=(const CancelBlock&);
577 public:
578 /**
579  * Makes the thread uncancellable, even if the code passes through a
580  * cancellation point, while the CancelBlock object exists (when the
581  * CancelBlock object ceases to exist, cancellation state is returned
582  * to the state prior to it being constructed). It should only be
583  * called by the thread which created the CancelBlock object. This
584  * method will not throw.
585  * @param old_state Indicates the cancellation state of the calling
586  * thread immediately before this call to block() was made, either
587  * PTHREAD_CANCEL_ENABLE (if the thread was previously cancellable) or
588  * PTHREAD_CANCEL_DISABLE (if this call did nothing because the thread
589  * was already uncancellable).
590  * @return 0 if successful, else a value other than 0.
591  */
592  static int block(int& old_state) {return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);}
593 
594 /**
595  * Makes the thread uncancellable, even if the code passes through a
596  * cancellation point, while the CancelBlock object exists (when the
597  * CancelBlock object ceases to exist, cancellation state is returned
598  * to the state prior to it being constructed). It should only be
599  * called by the thread which created the CancelBlock object. This
600  * method will not throw.
601  * @return 0 if successful, else a value other than 0.
602  */
603  static int block() {int old_state; return block(old_state);}
604 
605 /**
606  * Makes the thread cancellable while the CancelBlock object exists
607  * (when the CancelBlock object ceases to exist, cancellation state is
608  * returned to the state prior to it being constructed). It should
609  * only be called by the thread which created the CancelBlock object.
610  * This method will not throw. The 'Detailed Description' section
611  * above has information about the issues to be taken into account if
612  * a call to this method is to be made.
613  * @param old_state Indicates the cancellation state of the calling
614  * thread immediately before this call to unblock() was made, either
615  * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable)
616  * or PTHREAD_CANCEL_ENABLE (if this call did nothing because the
617  * thread was already cancellable).
618  * @return 0 if successful, else a value other than 0.
619  */
620  static int unblock(int& old_state) {return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);}
621 
622 /**
623  * Makes the thread cancellable while the CancelBlock object exists
624  * (when the CancelBlock object ceases to exist, cancellation state is
625  * returned to the state prior to it being constructed). It should
626  * only be called by the thread which created the CancelBlock object.
627  * This method will not throw. The 'Detailed Description' section
628  * above has information about the issues to be taken into account if
629  * a call to this method is to be made.
630  * @return 0 if successful, else a value other than 0.
631  */
632  static int unblock() {int old_state; return unblock(old_state);}
633 
634 /**
635  * Restores cancellation state to the state it was in immediately
636  * before this CancelBlock object was constructed. It should only be
637  * called by the thread which created the CancelBlock object. This
638  * method will not throw.
639  * @param old_state Indicates the cancellation state of the calling
640  * thread immediately before this call to restore() was made, either
641  * PTHREAD_CANCEL_DISABLE (if the thread was previously uncancellable)
642  * or PTHREAD_CANCEL_ENABLE (if this thread was previously
643  * cancellable).
644  * @return 0 if successful, else a value other than 0.
645  *
646  * Since 0.9.1
647  */
648  int restore(int& old_state) {return pthread_setcancelstate(starting_state, &old_state);}
649 
650 /**
651  * Restores cancellation state to the state it was in immediately
652  * before this CancelBlock object was constructed. It should only be
653  * called by the thread which created the CancelBlock object. This
654  * method will not throw.
655  * @return 0 if successful, else a value other than 0.
656  *
657  * Since 0.9.1
658  */
659  int restore() {int old_state; return restore(old_state);}
660 
661 /**
662  * The constructor will not throw.
663  * @param blocking Whether the CancelBlock object should start in
664  * blocking mode. The 'Detailed Description' section above has
665  * information about the issues to be taken into account if 'false' is
666  * passed to this parameter.
667  */
668  CancelBlock(bool blocking = true);
669 
670 /**
671  * The destructor will put the thread in the cancellation state that
672  * it was in immediately before the CancelBlock object was constructed
673  * (which might be blocking). It will not throw.
674  *
675  * This behaviour is from version 0.9.1. In version 0.9.0
676  * cancellation state was always made non-blocking by the destructor.
677  */
679 
680 /* Only has effect if --with-glib-memory-slices-compat or
681  * --with-glib-memory-slices-no-compat option picked */
683 };
684 
685 /**
686  * @class Exit thread.h c++-gtk-utils/thread.h
687  * @brief A class which can be thrown to terminate the throwing
688  * thread.
689  *
690  * This class can be thrown (instead of calling pthread_exit()) when a
691  * thread wishes to terminate itself and also ensure stack unwinding,
692  * so that destructors of local objects are called. It is caught
693  * automatically by the implementation of Cgu::Thread::Thread::start()
694  * so that it will only terminate the thread throwing it and not the
695  * whole process. See the Cgu::Thread::Thread::cancel() method above,
696  * for use when a thread wishes to terminate another one, and the
697  * caveats on the use of Cgu::Thread::Thread::cancel().
698  *
699  * Do not throw a Cgu::Thread::Exit object in a program with more than
700  * one main loop in order to terminate one of the threads which has
701  * its own main loop. Instead, just cause its main loop to terminate
702  * by, say, calling g_main_loop_quit() on it.
703  */
704 class Exit {};
705 
706 } // namespace Thread
707 
708 } // namespace Cgu
709 
710 #endif
Cgu::Thread::JoinableHandle::cancel
void cancel()
Cgu::Callback::CallbackArg
The callback interface class.
Definition: callback.h:904
Cgu
Definition: application.h:45
Cgu::Thread::JoinableHandle
A class wrapping a Thread::Thread object representing a joinable thread.
Definition: thread.h:298
Cgu::Thread::CancelBlock::restore
int restore(int &old_state)
Definition: thread.h:648
Cgu::Thread::JoinableHandle::operator=
JoinableHandle & operator=(JoinableHandle &h)
Cgu::Thread::Thread::cancel
void cancel()
Definition: thread.h:110
Cgu::Thread::JoinableHandle::join_on_exit
@ join_on_exit
Definition: thread.h:300
Cgu::Thread::Thread::join
void join()
Definition: thread.h:122
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle()
Definition: thread.h:515
Cgu::Thread::CancelBlock::~CancelBlock
~CancelBlock()
Definition: thread.h:678
Cgu::Thread::CancelBlock::restore
int restore()
Definition: thread.h:659
callback.h
This file provides classes encapsulating callbacks.
Cgu::Thread::CancelBlock::block
static int block()
Definition: thread.h:603
Cgu::Thread::JoinableHandle::Action
Action
Definition: thread.h:300
Cgu::Thread::Exit
A class which can be thrown to terminate the throwing thread.
Definition: thread.h:704
Cgu::Thread::CancelBlock::block
static int block(int &old_state)
Definition: thread.h:592
Cgu::Thread::JoinableHandle::~JoinableHandle
~JoinableHandle()
Cgu::Thread::CancelBlock::unblock
static int unblock()
Definition: thread.h:632
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle(std::auto_ptr< Cgu::Thread::Thread > thread, Action act)
Definition: thread.h:473
Cgu::Thread::JoinableHandle::is_caller
bool is_caller()
Cgu::Thread::JoinableHandle::detach
void detach()
Cgu::Thread::JoinableHandle::is_managing
bool is_managing()
Cgu::Thread::JoinableHandle::join
bool join()
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:300
Cgu::Thread::CancelBlock
A class enabling the cancellation state of a thread to be controlled.
Definition: thread.h:571
mutex.h
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Cgu::Thread::Thread::start
static std::auto_ptr< Cgu::Thread::Thread > start(const Cgu::Callback::Callback *cb, bool joinable)
Cgu::Thread::Thread::detach
void detach()
Definition: thread.h:131
Cgu::Thread::CancelBlock::unblock
static int unblock(int &old_state)
Definition: thread.h:620
Cgu::Thread::Thread::is_caller
bool is_caller()
Definition: thread.h:147
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:109
Cgu::Thread::Thread
A class representing a pthread thread.
Definition: thread.h:69
Cgu::Thread::JoinableHandle::JoinableHandle
JoinableHandle(JoinableHandle &h)
Definition: thread.h:503
cgu_config.h