c++-gtk-utils
mutex.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 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36 
37 */
38 
39 #ifndef CGU_MUTEX_H
40 #define CGU_MUTEX_H
41 
42 #include <exception>
43 #include <pthread.h>
44 #include <time.h>
45 
46 #include <glib.h>
48 
49 /**
50  * @file mutex.h
51  * @brief Provides wrapper classes for pthread mutexes and condition
52  * variables, and scoped locking classes for exception safe mutex
53  * locking.
54  * @note If the system supports monotonic clocks (and this library is
55  * not being cross-compiled onto a different architecture), then a
56  * system monotonic clock will be used in
57  * Cgu::Thread::Cond::timed_wait() and
58  * Cgu::Thread::Cond::get_abs_time(). This can be tested at run time
59  * with Cgu::Thread::Cond::have_monotonic_clock().
60  */
61 
62 namespace Cgu {
63 
64 namespace Thread {
65 
66 struct CondError: public std::exception {
67  virtual const char* what() const throw() {return "Thread::CondError";}
68 };
69 
70 /*
71  * Since version 1.2.0, which automatically checks for monotonic
72  * clocks in its configure script, this exception is no longer thrown.
73  * We keep the class just for source compatibility purposes.
74  */
75 #ifndef DOXYGEN_PARSING
76 struct CondSetClockError: public std::exception {
77  virtual const char* what() const throw() {return "Thread::CondSetClockError";}
78 };
79 #endif
80 
81 struct MutexError: public std::exception {
82  virtual const char* what() const throw() {return "Thread::MutexError";}
83 };
84 
85 struct RecMutexError: public std::exception {
86  virtual const char* what() const throw() {return "Thread::RecMutexError";}
87 };
88 
89 class Cond;
90 
91 /**
92  * @class Mutex mutex.h c++-gtk-utils/mutex.h
93  * @brief A wrapper class for pthread mutexes.
94  * @sa Thread::Thread Thread::Mutex::Lock Thread::Mutex::TrackLock Thread::Cond Thread::RecMutex
95  *
96  * This class can be used interchangeably with threads started with
97  * GThread and by this library, as both glib and this library use
98  * pthreads underneath on POSIX and other unix-like OSes. It can also
99  * in practice be used interchangeably with those started by C++11/14
100  * std::thread and with std::mutex and similar objects, as in C++11/14
101  * on unix-like OSes these facilities will be built on top of pthreads
102  * (for which purpose C++11/14 provides the std::native_handle_type
103  * type and std::thread::native_handle() function), or if they are
104  * not, they will use the same threading primitives provided by the
105  * kernel.
106  *
107  * Mutex objects can be constructed statically as well as dynamically
108  * and there is no need to call g_thread_init() before they are
109  * constructed, even if glib < 2.32 is used. (If created as a static
110  * object in global scope, it will not be possible to catch
111  * Thread::MutexError thrown by its constructor, but if a static
112  * global mutex throws there is nothing that could be done anyway
113  * except abort, and it would show that the pthreads installation is
114  * seriously defective.)
115  */
116 
117 class Mutex {
118  pthread_mutex_t pthr_mutex;
119 
120 public:
121  class Lock;
122  class TrackLock;
123  friend class Cond;
124 
125 /**
126  * This class cannot be copied. The copy constructor is deleted.
127  */
128  Mutex(const Mutex&) = delete;
129 
130 /**
131  * This class cannot be copied. The assignment operator is deleted.
132  */
133  Mutex& operator=(const Mutex&) = delete;
134 
135 /**
136  * Locks the mutex and acquires ownership. Blocks if already locked
137  * until it becomes free. It is not a cancellation point. It does
138  * not throw. It is thread safe.
139  * @return 0 if successful, otherwise the pthread mutex error number.
140  * @note With this library implementation, the only pthread error
141  * number which could be returned by this method is EDEADLK, which it
142  * would do if the default pthread mutex behaviour happens to return
143  * that error rather than deadlock in the case of recursive locking.
144  * Most default implementations do not do this and hence the return
145  * value is usually not worth checking for except during debugging.
146  */
147  int lock() noexcept {return pthread_mutex_lock(&pthr_mutex);}
148 
149 /**
150  * Tries to lock the mutex and acquire ownership, but returns
151  * immediately if it is already locked with value EBUSY. It is not a
152  * cancellation point. It does not throw. It is thread safe.
153  * @return 0 if successful, otherwise EBUSY.
154  * @note With this library implementation, the only pthread error
155  * number which could be returned by this method is EBUSY.
156  */
157  int trylock() noexcept {return pthread_mutex_trylock(&pthr_mutex);}
158 
159 /**
160  * Unlocks a locked mutex owned by the calling thread and relinquishes
161  * ownership. It is not a cancellation point. It does not throw. It
162  * must be called by the thread which owns the mutex.
163  * @return 0 if successful, otherwise the pthread mutex error number.
164  * @note With this library implementation, the only pthread error
165  * number which could be returned by this method is EPERM because the
166  * calling thread does not own the mutex (however POSIX does not
167  * require that return value in that case and hence the return value
168  * is usually not worth checking for except during debugging).
169  */
170  int unlock() noexcept {return pthread_mutex_unlock(&pthr_mutex);}
171 
172 /**
173  * Initialises the pthread mutex. It is not a cancellation point.
174  * @exception Cgu::Thread::MutexError Throws this exception if
175  * initialization of the mutex fails. (It is often not worth checking
176  * for this, as it means either memory is exhausted or pthread has run
177  * out of other resources to create new mutexes.)
178  */
179  Mutex() {if (pthread_mutex_init(&pthr_mutex, 0)) throw MutexError();}
180 
181 /**
182  * Destroys the pthread mutex. It is not a cancellation point. It
183  * does not throw. Destroying a mutex which is currently locked or
184  * associated with an active condition variable wait results in
185  * undefined behavior.
186  */
187  ~Mutex() {pthread_mutex_destroy(&pthr_mutex);}
188 
189 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
191 #endif
192 };
193 
194 // used as a second argument to Lock::Lock() and TrackLock::TrackLock
195 // in cases where the mutex has already been locked (say by Mutex::trylock())
196 enum Locked {locked};
197 // used as a second argument to TrackLock::TrackLock() in cases where
198 // locking of the mutex is to be deferred
200 
201 /**
202  * @class Mutex::Lock mutex.h c++-gtk-utils/mutex.h
203  * @brief A scoped locking class for exception safe Mutex locking.
204  * @sa Thread::Mutex Thread::Mutex::TrackLock Thread::Thread Thread::Cond
205  */
206 
207 class Mutex::Lock {
208  Mutex& mutex;
209 
210 public:
211  friend class Cond;
212 
213 /**
214  * This class cannot be copied. The copy constructor is deleted.
215  */
216  Lock(const Mutex::Lock&) = delete;
217 
218 /**
219  * This class cannot be copied. The assignment operator is deleted.
220  */
221  Mutex::Lock& operator=(const Mutex::Lock&) = delete;
222 
223 /**
224  * Calls Mutex::lock(), and so locks the mutex and reacquires
225  * ownership. It blocks if the mutex is already locked until the
226  * mutex becomes free. This method should normally only be called if
227  * a previous call has been made to Mutex::Lock::unlock() (that is,
228  * where the thread owning the Mutex::Lock object has temporarily
229  * allowed another thread to take the mutex concerned). It is not a
230  * cancellation point. It does not throw.
231  * @return 0 if successful, otherwise the pthread mutex error number.
232  * @note With this library implementation, the only pthread error
233  * number which could be returned by this method is EDEADLK, which it
234  * would do if the default pthread mutex behaviour happens to return
235  * that error rather than deadlock in the case of recursive locking.
236  * Most default implementations do not do this and hence the return
237  * value is usually not worth checking for except during debugging.
238  * @sa Mutex::TrackLock.
239  */
240  int lock() noexcept {return mutex.lock();}
241 
242 /**
243  * Calls Mutex::trylock(), and so tries to lock the mutex and
244  * reacquire ownership, but returns immediately if it is already
245  * locked with value EBUSY. This method should normally only be
246  * called if a previous call has been made to Mutex::Lock::unlock()
247  * (that is, where the thread owning the Mutex::Lock object has
248  * temporarily allowed another thread to take the mutex concerned).
249  * It is not a cancellation point. It does not throw.
250  * @return 0 if successful, otherwise EBUSY.
251  * @note With this library implementation, the only pthread error
252  * number which could be returned by this method is EBUSY.
253  * @sa Mutex::TrackLock.
254  */
255  int trylock() noexcept {return mutex.trylock();}
256 
257 /**
258  * Calls Mutex::unlock(), and so unlocks a locked mutex owned by the
259  * calling thread and relinquishes ownership (so temporarily allowing
260  * another thread to take the mutex). This method should normally
261  * only be called if it is to be followed by a call to
262  * Mutex::Lock::lock() or a successful call to Mutex::Lock::trylock()
263  * before the Mutex::Lock object concerned goes out of scope
264  * (otherwise Mutex::Lock's destructor will attempt to unlock an
265  * already unlocked mutex or a mutex of which another thread has by
266  * then taken ownership - Mutex::Lock objects do not maintain state).
267  * See Mutex::TrackLock::unlock() for a safe version of this method.
268  * It is not a cancellation point. It does not throw.
269  * @return 0 if successful, otherwise the pthread mutex error number.
270  * @note With this library implementation, the only pthread error
271  * number which could be returned by this method is EPERM because the
272  * calling thread does not own the mutex (however POSIX does not
273  * require that return value in that case and hence the return value
274  * is usually not worth checking for except during debugging).
275  * @sa Mutex::TrackLock.
276  */
277  int unlock() noexcept {return mutex.unlock();}
278 
279 /**
280  * This constructor locks the mutex passed to it. It is not a
281  * cancellation point. It does not throw.
282  * @param mutex_ The mutex to be locked.
283  */
284  Lock(Mutex& mutex_) noexcept: mutex(mutex_) {mutex.lock();}
285 
286 /**
287  * This constructor takes an already locked mutex (say as a result of
288  * Mutex::trylock()), and takes ownership of it. It is not a
289  * cancellation point. It does not throw.
290  * @param mutex_ The mutex to be managed by this object.
291  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
292  */
293  Lock(Mutex& mutex_, Locked tag) noexcept: mutex(mutex_) {}
294 
295 /**
296  * This class requires initialisation with a Mutex. The default
297  * constructor is deleted.
298  */
299  Lock() = delete;
300 
301 /**
302  * The destructor unlocks the owned mutex. It is not a cancellation
303  * point. It does not throw.
304  */
305  ~Lock() {mutex.unlock();}
306 
307 /* Only has effect if --with-glib-memory-slices-compat or
308  * --with-glib-memory-slices-no-compat option picked */
310 };
311 
312 /**
313  * @class Mutex::TrackLock mutex.h c++-gtk-utils/mutex.h
314  * @brief A scoped locking class for exception safe Mutex locking
315  * which tracks the status of its mutex.
316  * @sa Thread::Mutex Thread::Mutex::Lock Thread::Thread Thread::Cond
317  *
318  * This class is similar to a Mutex::Lock object, except that it
319  * tracks whether the mutex it manages is locked by the thread
320  * creating the Mutex::TrackLock object (provided that, while the
321  * Mutex::TrackLock object exists, the thread creating it only
322  * accesses the mutex through that object). This enables
323  * Mutex::TrackLock::unlock() to be used without it being followed
324  * later by a call to Mutex::TrackLock::lock() or a successful call to
325  * Mutex::TrackLock::trylock(), and also permits locking to be
326  * deferred until after construction of the lock object. Note that
327  * only one thread may call the methods of any one Mutex::TrackLock
328  * object, including causing its destructor to be invoked.
329  */
330 
332  Mutex& mutex;
333  bool owner;
334 
335 public:
336  friend class Cond;
337 
338 /**
339  * This class cannot be copied. The copy constructor is deleted.
340  */
341  TrackLock(const Mutex::TrackLock&) = delete;
342 
343 /**
344  * This class cannot be copied. The assignment operator is deleted.
345  */
346  Mutex::TrackLock& operator=(const Mutex::TrackLock&) = delete;
347 
348 /**
349  * Calls Mutex::lock(), and so locks the mutex and acquires ownership.
350  * It blocks if the mutex is already locked until the mutex becomes
351  * free. This method should normally only be called if a previous
352  * call has been made to Mutex::TrackLock::unlock() or this
353  * Mutex::TrackLock object has been constructed with the Thread::defer
354  * enum tag. It is not a cancellation point. It does not throw.
355  * @return 0 if successful, otherwise the pthread mutex error number.
356  * @note With this library implementation, the only pthread error
357  * number which could be returned by this method is EDEADLK, which it
358  * would do if the default pthread mutex behaviour happens to return
359  * that error rather than deadlock in the case of recursive locking.
360  * Most default implementations do not do this and hence the return
361  * value is usually not worth checking for except during debugging.
362  */
363  int lock() noexcept {int ret = mutex.lock(); if (!owner) owner = !ret; return ret;}
364 
365 /**
366  * Calls Mutex::trylock(), and so tries to lock the mutex and acquire
367  * ownership, but returns immediately if it is already locked with
368  * value EBUSY. This method should normally only be called if a
369  * previous call has been made to Mutex::TrackLock::unlock() or this
370  * Mutex::TrackLock object has been constructed with the Thread::defer
371  * enum tag. It is not a cancellation point. It does not throw.
372  * @return 0 if successful, otherwise EBUSY.
373  * @note With this library implementation, the only pthread error
374  * number which could be returned by this method is EBUSY.
375  */
376  int trylock() noexcept {int ret = mutex.trylock(); if (!owner) owner = !ret; return ret;}
377 
378 /**
379  * Calls Mutex::unlock(), and so unlocks a locked mutex owned by the
380  * calling thread. It will cause is_owner() to return false unless a
381  * subsequent call is made to lock() or a subsequent successful call
382  * is made to trylock(). It is not a cancellation point. It does not
383  * throw.
384  * @return 0 if successful, otherwise the pthread mutex error number.
385  * @note With this library implementation, the only pthread error
386  * number which could be returned by this method is EPERM because the
387  * calling thread does not own the mutex (however POSIX does not
388  * require that return value in that case and hence the return value
389  * is usually not worth checking for except during debugging).
390  */
391  int unlock() noexcept {int ret = mutex.unlock(); if (owner) owner = ret; return ret;}
392 
393 /**
394  * Indicates whether the mutex managed by this Mutex::TrackLock object
395  * is locked, and so owned, by it. It does not throw.
396  * @return true if the mutex is locked by this object, otherwise
397  * false.
398  */
399  bool is_owner() const noexcept {return owner;}
400 
401 /**
402  * This constructor locks the mutex passed to it. It is not a
403  * cancellation point. It does not throw.
404  * @param mutex_ The mutex to be locked.
405  */
406  TrackLock(Mutex& mutex_) noexcept: mutex(mutex_), owner(true) {mutex.lock();}
407 
408 /**
409  * This constructor takes an already locked mutex (say as a result of
410  * Mutex::trylock()), and takes ownership of it. It is not a
411  * cancellation point. It does not throw.
412  * @param mutex_ The mutex to be managed by this object.
413  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
414  */
415  TrackLock(Mutex& mutex_, Locked tag) noexcept: mutex(mutex_), owner(true) {}
416 
417 /**
418  * This constructor defers locking of the mutex (and so taking
419  * ownership of it) until an explicit call to lock() or trylock() is
420  * made. It is not a cancellation point. It does not throw.
421  * @param mutex_ The mutex to be managed by this object.
422  * @param tag Pass the Cgu::Thread::defer enum tag to this parameter.
423  */
424  TrackLock(Mutex& mutex_, DeferLock tag) noexcept: mutex(mutex_), owner(false) {}
425 
426 /**
427  * This class requires initialisation with a Mutex. The default
428  * constructor is deleted.
429  */
430  TrackLock() = delete;
431 
432 /**
433  * The destructor unlocks the managed mutex if it is locked. It is
434  * not a cancellation point. It does not throw.
435  */
436  ~TrackLock() {if (owner) mutex.unlock();}
437 
438 /* Only has effect if --with-glib-memory-slices-compat or
439  * --with-glib-memory-slices-no-compat option picked */
441 };
442 
443 /**
444  * @class Cond mutex.h c++-gtk-utils/mutex.h
445  * @brief A wrapper class for pthread condition variables.
446  * @sa Thread::Thread Thread::Mutex Thread::Mutex::Lock Thread::Mutex::TrackLock
447  */
448 
449 class Cond {
450  pthread_cond_t cond;
451 
452 public:
453 
454 /**
455  * This class cannot be copied. The copy constructor is deleted.
456  */
457  Cond(const Cond&) = delete;
458 
459 /**
460  * This class cannot be copied. The assignment operator is deleted.
461  */
462  Cond& operator=(const Cond&) = delete;
463 
464 /**
465  * Unblock at least one thread waiting on this condition variable.
466  * Can be called by any thread. It is not a cancellation point. Does
467  * not throw.
468  * @return 0 if successful, otherwise the pthread error number.
469  * @note With this library implementation, no pthread error should
470  * arise so there is no need to check the return value.
471  */
472  int signal() noexcept {return pthread_cond_signal(&cond);}
473 
474 /**
475  * Unblocks all threads waiting on this condition variable, which
476  * acquire the mutex in an order determined by the scheduling policy.
477  * Can be called by any thread. It is not a cancellation point. Does
478  * not throw.
479  * @return 0 if successful, otherwise the pthread error number.
480  * @note With this library implementation, no pthread error should
481  * arise so there is no need to check the return value.
482  */
483  int broadcast() noexcept {return pthread_cond_broadcast(&cond);}
484 
485 /**
486  * Waits on this condition variable until awoken. It must be called
487  * by the thread which owns the mutex. Re-acquires the mutex when
488  * awoken. It is a cancellation point. This method is cancellation
489  * safe even if the stack does not unwind on cancellation (but if the
490  * stack does not unwind some other way of destroying this object on
491  * cancellation is required, such as by having it allocated on
492  * freestore and deleted in a cancellation clean-up handler). This
493  * method does not throw.
494  * @param mutex The locked mutex associated with the wait which is
495  * re-acquired on being awoken.
496  * @return 0 after being awoken on waiting, otherwise the pthread
497  * error number.
498  * @note 1. pthread condition variables can, as a matter of design,
499  * awake spontaneously (and Cond::signal() may awaken more than one
500  * thread). Therefore the relevant condition should be tested in a
501  * while loop and not in an if block. 0 will be returned on a
502  * spontaneous awakening.
503  * @note 2. With this library implementation, the only pthread error
504  * numbers which could be returned are EINVAL (if the mutex argument
505  * is not a valid mutex) or EPERM (if the thread calling this method
506  * does not own the mutex).
507  * @note 3. Between versions 2.2.3 and 2.2.13 inclusive, this method
508  * was marked 'noexcept'. This was a mistake because it prevented a
509  * thread being cancelled while in a wait (the cancellation
510  * pseudo-exception conflicted with the noexcept specifier). This was
511  * fixed in version 2.2.14.
512  */
513  int wait(Mutex& mutex) {return pthread_cond_wait(&cond, &mutex.pthr_mutex);}
514 
515 /**
516  * Does the same as Cond::wait(Mutex&), except that as a convenience
517  * it will take a Mutex::Lock object handling the Mutex object as an
518  * alternative to passing the Mutex object itself.
519  * @note Between versions 2.2.3 and 2.2.13 inclusive, this method was
520  * marked 'noexcept'. This was a mistake because it prevented a
521  * thread being cancelled while in a wait (the cancellation
522  * pseudo-exception conflicted with the noexcept specifier). This was
523  * fixed in version 2.2.14.
524  */
525  int wait(Mutex::Lock& lock) {return wait(lock.mutex);}
526 
527 /**
528  * Does the same as Cond::wait(Mutex&), except that as a convenience
529  * it will take a Mutex::TrackLock object handling the Mutex object as
530  * an alternative to passing the Mutex object itself.
531  * @note Between versions 2.2.3 and 2.2.13 inclusive, this method was
532  * marked 'noexcept'. This was a mistake because it prevented a
533  * thread being cancelled while in a wait (the cancellation
534  * pseudo-exception conflicted with the noexcept specifier). This was
535  * fixed in version 2.2.14.
536  */
537  int wait(Mutex::TrackLock& lock) {return wait(lock.mutex);}
538 
539 /**
540  * Waits on this condition variable until awoken (in which case it
541  * re-acquires the mutex), or until the timeout expires (in which case
542  * it re-acquires the mutex and returns with ETIMEDOUT). It must be
543  * called by the thread which owns the mutex. Re-acquires the mutex
544  * when awoken or timing out. It is a cancellation point. This
545  * method is cancellation safe even if the stack does not unwind on
546  * cancellation (but if the stack does not unwind some other way of
547  * destroying this object on cancellation is required, such as by
548  * having it allocated on freestore and deleted in a cancellation
549  * clean-up handler). This method does not throw.
550  * @param mutex The locked mutex associated with the wait which is
551  * re-acquired on being awoken or timing out.
552  * @param abs_time The time at which the wait will unblock if not
553  * previously awoken. A suitable value can be obtained by calling
554  * the get_abs_time() function.
555  * @return 0 after being awoken on waiting, otherwise ETIMEDOUT or
556  * other pthread error number.
557  * @note 1. With this library implementation, apart from ETIMEDOUT,
558  * the only pthread error numbers which could be returned are EINVAL
559  * (if the mutex argument is not a valid mutex or the abs_time
560  * argument does not comprise a valid timespec struct) or EPERM (if
561  * the thread calling this method does not own the mutex).
562  * @note 2. pthread condition variables can, as a matter of design,
563  * awake spontaneously (and Cond::signal() may awaken more than one
564  * thread). Therefore the relevant condition should be tested in a
565  * while loop and not in an if block. 0 will be returned on a
566  * spontaneous awakening.
567  * @note 3. If the system supports monotonic clocks (and this library
568  * is not being cross-compiled onto a different architecture), then
569  * condition variables will use a monotonic clock in
570  * Cond::timed_wait() and Cond::get_abs_time(). This can be tested at
571  * run time with Cond::have_monotonic_clock().
572  * @note 4. Between versions 2.2.3 and 2.2.13 inclusive, this method
573  * was marked 'noexcept'. This was a mistake because it prevented a
574  * thread being cancelled while in a wait (the cancellation
575  * pseudo-exception conflicted with the noexcept specifier). This was
576  * fixed in version 2.2.14.
577  */
578  int timed_wait(Mutex& mutex, const timespec& abs_time) {
579  return pthread_cond_timedwait(&cond, &mutex.pthr_mutex, &abs_time);
580  }
581 
582 /**
583  * Does the same as Cond::timed_wait(Mutex&, const timespec&), except
584  * that as a convenience it will take a Mutex::Lock object handling
585  * the Mutex object as an alternative to passing the Mutex object
586  * itself.
587  * @note Between versions 2.2.3 and 2.2.13 inclusive, this method was
588  * marked 'noexcept'. This was a mistake because it prevented a
589  * thread being cancelled while in a wait (the cancellation
590  * pseudo-exception conflicted with the noexcept specifier). This was
591  * fixed in version 2.2.14.
592  */
594  const timespec& abs_time) {return timed_wait(lock.mutex, abs_time);}
595 
596 /**
597  * Does the same as Cond::timed_wait(Mutex&, const timespec&), except
598  * that as a convenience it will take a Mutex::TrackLock object
599  * handling the Mutex object as an alternative to passing the Mutex
600  * object itself.
601  * @note Between versions 2.2.3 and 2.2.13 inclusive, this method was
602  * marked 'noexcept'. This was a mistake because it prevented a
603  * thread being cancelled while in a wait (the cancellation
604  * pseudo-exception conflicted with the noexcept specifier). This was
605  * fixed in version 2.2.14.
606  */
608  const timespec& abs_time) {return timed_wait(lock.mutex, abs_time);}
609 
610 /**
611  * This is a utility function that inserts into a timespec structure
612  * the current time plus a given number of milliseconds ahead, which
613  * can be applied to a call to Cond::timed_wait(). It does not throw.
614  * It is thread-safe.
615  * @param ts A timespec object into which the result of current time +
616  * millisec will be placed.
617  * @param millisec The number of milliseconds ahead of current time to
618  * which the timespec object will be set.
619  * @note If the system supports monotonic clocks (and this library is
620  * not being cross-compiled onto a different architecture), then
621  * condition variables will use a system monotonic clock in this
622  * method and Cond::timed_wait(). This can be tested at run time with
623  * Cond::have_monotonic_clock().
624  */
625  static void get_abs_time(timespec& ts, unsigned int millisec);
626 
627 /**
628  * Indicates whether the library has been compiled with support for
629  * monotonic clocks in Cond::timed_wait(). Most recent linux and BSD
630  * distributions will support them, and this function would normally
631  * return true unless the library has been cross-compiled from one
632  * platform to a different platform. This function can be tested at
633  * program initialization, and if they are not supported a warning can
634  * be given to the user about the deficiences of using the system
635  * clock for timed events. It does not throw. It is thread safe.
636  * @return true if the library has been compiled with support for
637  * monotonic clocks in Cond::timed_wait(), otherwise false.
638  */
639  static bool have_monotonic_clock();
640 
641 /**
642  * Initialises the pthread condition variable. It is not a
643  * cancellation point.
644  * @exception Cgu::Thread::CondError Throws this exception if
645  * initialization of the condition variable fails. (It is often not
646  * worth checking for CondError, as it means either memory is
647  * exhausted or pthread has run out of other resources to create new
648  * condition variables.)
649  * @note If the system supports monotonic clocks (and this library is
650  * not being cross-compiled onto a different architecture), then
651  * condition variables will use a system monotonic clock in
652  * Cond::timed_wait() and Cond::get_abs_time(). This can be tested at
653  * run time by calling Cond::have_monotonic_clock().
654  */
655  Cond();
656 
657 /**
658  * Destroys the pthread condition variable. It is not a cancellation
659  * point. The destructor does not throw. Destroying a condition
660  * variable on which another thread is currently blocked results in
661  * undefined behavior.
662  */
663  ~Cond(void) {pthread_cond_destroy(&cond);}
664 
665 /* Only has effect if --with-glib-memory-slices-compat or
666  * --with-glib-memory-slices-no-compat option picked */
668 };
669 
670 /**
671  * @class RecMutex mutex.h c++-gtk-utils/mutex.h
672  * @brief A wrapper class for pthread mutexes which provides a
673  * recursive mutex.
674  * @sa Thread::Thread Thread::RecMutex::Lock Thread::RecMutex::TrackLock Thread::Mutex
675  *
676  * This class can be used interchangeably with threads started with
677  * GThread and by this library, as both glib and this library use
678  * pthreads underneath on POSIX and other unix-like OSes. It can also
679  * in practice be used interchangeably with those started by C++11/14
680  * std::thread and with std::recursive_mutex and similar objects, as
681  * in C++11/14 on unix-like OSes these facilities will be built on top
682  * of pthreads (for which purpose C++11/14 provides the
683  * std::native_handle_type type and std::thread::native_handle()
684  * function), or if they are not, they will use the same threading
685  * primitives provided by the kernel.
686  *
687  * RecMutex objects can be constructed statically as well as
688  * dynamically and there is no need to call g_thread_init() before
689  * they are constructed, even if glib < 2.32 is used. (If created as
690  * a static object in global scope, it will not be possible to catch
691  * Thread::MutexError or Thread::RecMutexError thrown by its
692  * constructor, but if a static global mutex throws there is nothing
693  * that could be done anyway except abort.)
694  *
695  * See the comments below on the test_support() method of this class,
696  * about how the system's support for native recursive mutexes can be
697  * tested at runtime and when a user program is compiled. If glib >=
698  * 2.32 is installed, it can be assumed that native recursive mutexes
699  * are available, as glib >= 2.32 also uses them.
700  */
701 
702 class RecMutex {
703  pthread_mutex_t pthr_mutex;
704 
705 public:
706  class Lock;
707  class TrackLock;
708 
709 /**
710  * This class cannot be copied. The copy constructor is deleted.
711  */
712  RecMutex(const RecMutex&) = delete;
713 
714 /**
715  * This class cannot be copied. The assignment operator is deleted.
716  */
717  RecMutex& operator=(const RecMutex&) = delete;
718 
719 /**
720  * Locks the mutex and acquires ownership. Blocks if already locked
721  * until it becomes free, unless the calling thread already holds the
722  * lock, in which case it increments the lock count and returns
723  * immediately. It is not a cancellation point. It does not throw.
724  * It is thread safe.
725  * @return 0 if successful, otherwise the pthread mutex error number.
726  * @note With this library implementation, the only pthread error
727  * number which could be returned by this method is EAGAIN, which it
728  * would do if the maximum recursive lock count for this mutex has
729  * been reached. Usually this number is at or around INT_MAX and
730  * hence the return value is usually not worth checking for except
731  * during debugging.
732  */
733  int lock() noexcept {return pthread_mutex_lock(&pthr_mutex);}
734 
735 /**
736  * Tries to lock the mutex and acquire ownership, but returns
737  * immediately if it is already locked with value EBUSY unless the
738  * calling thread already holds the lock, in which case it returns
739  * normally and increments the lock count. It is not a cancellation
740  * point. It does not throw. It is thread safe.
741  * @return 0 if successful, otherwise EBUSY or other pthread mutex
742  * error number.
743  * @note With this library implementation, apart from EBUSY, the only
744  * other pthread error number which could be returned by this method
745  * is EAGAIN, which it would do if the maximum recursive lock count
746  * for this mutex has been reached. Usually this number is at or
747  * around INT_MAX and hence an EAGAIN error return value is usually
748  * not worth checking for except during debugging.
749  */
750  int trylock() noexcept {return pthread_mutex_trylock(&pthr_mutex);}
751 
752 /**
753  * Unlocks a locked mutex owned by the calling thread and either
754  * relinquishes ownership (if the mutex has not been recursively
755  * locked) or decrements the lock count (if it has). It is not a
756  * cancellation point. It does not throw. It must be called by the
757  * thread which owns the mutex.
758  * @return 0 if successful, otherwise the pthread mutex error number.
759  * @note With this library implementation, the only pthread error
760  * number which could be returned by this method is EPERM because the
761  * calling thread does not own the mutex (however POSIX does not
762  * require that return value in that case and hence the return value
763  * is usually not worth checking for except during debugging).
764  */
765  int unlock() noexcept {return pthread_mutex_unlock(&pthr_mutex);}
766 
767 /**
768  * Indicates whether the system supports recursive mutexes. This
769  * method does not throw. It is thread safe.
770  * @return 0 if the system supports recursive mutexes, -1 if it does
771  * not support recursive mutexes and 1 if pthread has run out of
772  * sufficient resources to test this at run time (in which case any
773  * attempt to create mutexes or start threads is likely to fail).
774  * Practically all recent linux and BSD distributions will support
775  * them, and this function would normally return 0. If it does not,
776  * it is still possible to use GStaticRecMutex objects (for which
777  * purpose see Cgu::Thread::GrecmutexLock).
778  *
779  * @note The header file <c++-gtk-utils/cgu_config.h> defines the
780  * symbol CGU_HAVE_RECURSIVE_MUTEX if native recursive mutexes were
781  * found to be supported when this library was compiled. Programs
782  * using this library can therefore test for that symbol with the
783  * pre-processor for conditional compilation purposes (so that the
784  * program can, for example, be compiled to use GStaticRecMutex if
785  * that symbol is not defined). However, if the library was
786  * cross-compiled from one architecture to another, that symbol may
787  * not be defined even though the target architecture does, in fact,
788  * support them at program runtime. In other words, if
789  * CGU_HAVE_RECURSIVE_MUTEX is defined then this method will always
790  * return 0; but in the event of cross-compilation of the library this
791  * method (which provides a separate runtime test) might return 0,
792  * correctly showing support, even when CGU_HAVE_RECURSIVE_MUTEX is
793  * not defined.
794  *
795  * @note If glib >= 2.32 is installed, it can be assumed that native
796  * recursive mutexes are available, as glib >= 2.32 also uses them.
797  */
798  static int test_support();
799 
800 /**
801  * Initialises the pthread mutex. It is not a cancellation point.
802  * @exception Cgu::Thread::RecMutexError Throws this exception if the
803  * system does not support recursive mutexes. (If this has been
804  * checked beforehand, say by calling test_support(), there should be
805  * no need to check for this exception.)
806  * @exception Cgu::Thread::MutexError Throws this exception if
807  * initialization of the mutex fails, except because the system does
808  * not support recursive mutexes. (It is often not worth checking for
809  * MutexError, as it means either memory is exhausted or pthread has
810  * run out of other resources to create new mutexes.)
811  */
812  RecMutex();
813 
814 /**
815  * Destroys the pthread mutex. It is not a cancellation point. It
816  * does not throw. Destroying a mutex which is currently locked
817  * results in undefined behavior.
818  */
819  ~RecMutex() {pthread_mutex_destroy(&pthr_mutex);}
820 
821 /* Only has effect if --with-glib-memory-slices-compat or
822  * --with-glib-memory-slices-no-compat option picked */
824 };
825 
826 /**
827  * @class RecMutex::Lock mutex.h c++-gtk-utils/mutex.h
828  * @brief A scoped locking class for exception safe RecMutex locking.
829  * @sa Thread::RecMutex Thread::RecMutex::TrackLock Thread::Thread
830  */
831 
833  RecMutex& mutex;
834 
835 public:
836 /**
837  * This class cannot be copied. The copy constructor is deleted.
838  */
839  Lock(const RecMutex::Lock&) = delete;
840 
841 /**
842  * This class cannot be copied. The assignment operator is deleted.
843  */
844  RecMutex::Lock& operator=(const RecMutex::Lock&) = delete;
845 
846 /**
847  * This calls RecMutex::lock(), and so locks the mutex and reacquires
848  * ownership. It blocks if the mutex is already locked until the
849  * mutex becomes free, unless the calling thread already holds the
850  * lock, in which case it increments the lock count and returns
851  * immediately. This method should normally only be called if a
852  * previous call has been made to RecMutex::Lock::unlock() (that is,
853  * where the thread owning the RecMutex::Lock object has temporarily
854  * allowed another thread to take the mutex concerned if it is not
855  * recursively locked). It is not a cancellation point. It does not
856  * throw.
857  * @return 0 if successful, otherwise the pthread mutex error number.
858  * @note With this library implementation, the only pthread error
859  * number which could be returned by this method is EAGAIN, which it
860  * would do if the maximum recursive lock count for the particular
861  * mutex in question has been reached. Usually this number is at or
862  * around INT_MAX and hence the return value is usually not worth
863  * checking for except during debugging.
864  * @sa RecMutex::TrackLock.
865  */
866  int lock() noexcept {return mutex.lock();}
867 
868 /**
869  * This calls RecMutex::trylock(), and so tries to lock the mutex and
870  * reacquire ownership, but returns immediately if it is already
871  * locked with value EBUSY unless the calling thread already holds the
872  * lock, in which case it returns normally and increments the lock
873  * count. This method should normally only be called if a previous
874  * call has been made to RecMutex::Lock::unlock() (that is, where the
875  * thread owning the RecMutex::Lock object has temporarily allowed
876  * another thread to take the mutex concerned if it is not recursively
877  * locked). It is not a cancellation point. It does not throw.
878  * @return 0 if successful, otherwise EBUSY or other pthread mutex
879  * error number.
880  * @note With this library implementation, apart from EBUSY, the only
881  * other pthread error number which could be returned by this method
882  * is EAGAIN, which it would do if the maximum recursive lock count
883  * for the particular mutex in question has been reached. Usually
884  * this number is at or around INT_MAX and hence an EAGAIN error
885  * return value is usually not worth checking for except during
886  * debugging.
887  * @sa RecMutex::TrackLock.
888  */
889  int trylock() noexcept {return mutex.trylock();}
890 
891 /**
892  * This calls RecMutex::unlock() and so unlocks a locked mutex owned
893  * by the calling thread, so temporarily allowing another thread to
894  * take the mutex if the mutex has not been recursively locked, or if
895  * it has been recursively locked decrements the lock count, so
896  * temporarily relinquishing ownership. This method should normally
897  * only be called if it is to be followed by a call to
898  * RecMutex::Lock::lock() or a successful call to
899  * RecMutex::Lock::trylock() before the RecMutex::Lock object
900  * concerned goes out of scope (otherwise RecMutex::Lock's destructor
901  * will attempt to decrement the lock count of a mutex which already
902  * has a lock count of 0 or which another thread has by then taken
903  * ownership or leave the lock count in an unbalanced condition -
904  * RecMutex::Lock objects do not maintain state). See
905  * RecMutex::TrackLock::unlock() for a safe version of this method.
906  * It is not a cancellation point. It does not throw.
907  * @return 0 if successful, otherwise the pthread mutex error number.
908  * @note With this library implementation, the only pthread error
909  * number which could be returned by this method is EPERM because the
910  * calling thread does not own the particular mutex in question
911  * (however POSIX does not require that return value in that case and
912  * hence the return value is usually not worth checking for except
913  * during debugging).
914  * @sa RecMutex::TrackLock.
915  */
916  int unlock() noexcept {return mutex.unlock();}
917 
918 /**
919  * This constructor locks the mutex passed to it. See
920  * RecMutex::lock() for a description of the outcomes. It is not a
921  * cancellation point.
922  * @param mutex_ The mutex to be locked.
923  * @exception Cgu::Thread::RecMutexError Throws this exception if
924  * initialization of the mutex fails because the maximum recursive
925  * lock count for the particular mutex in question has been reached.
926  * Usually this number is at or around INT_MAX so it is not usually
927  * useful to check for it except during debugging.
928  */
929  Lock(RecMutex& mutex_): mutex(mutex_) {if (mutex.lock()) throw RecMutexError();}
930 
931 /**
932  * This constructor takes an already locked mutex (say as a result of
933  * RecMutex::trylock()), and takes ownership of it. It is not a
934  * cancellation point. It does not throw.
935  * @param mutex_ The mutex to be managed by this object.
936  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
937  */
938  Lock(RecMutex& mutex_, Locked tag) noexcept: mutex(mutex_) {}
939 
940 /**
941  * This class requires initialisation with a RecMutex. The default
942  * constructor is deleted.
943  */
944  Lock() = delete;
945 
946 /**
947  * The destructor unlocks the owned mutex. See RecMutex::unlock() for
948  * a description of the outcomes. It is not a cancellation point. It
949  * does not throw.
950  */
951  ~Lock() {mutex.unlock();}
952 
953 /* Only has effect if --with-glib-memory-slices-compat or
954  * --with-glib-memory-slices-no-compat option picked */
956 };
957 
958 /**
959  * @class RecMutex::TrackLock mutex.h c++-gtk-utils/mutex.h
960  * @brief A scoped locking class for exception safe RecMutex locking
961  * which tracks the status of its mutex.
962  * @sa Thread::RecMutex Thread::RecMutex::Lock Thread::Thread
963  *
964  * This class is similar to a RecMutex::Lock object, except that it
965  * tracks whether the mutex it manages is locked by the thread
966  * creating the RecMutex::TrackLock object with respect to the
967  * particular locking operation to be governed by the object (provided
968  * that, while the RecMutex::TrackLock object exists, the thread
969  * creating it only accesses the mutex with respect that particular
970  * operation through that object). This enables
971  * RecMutex::TrackLock::unlock() to be used without it being followed
972  * later by a call to RecMutex::TrackLock::lock() or a successful call
973  * to RecMutex::TrackLock::trylock(), and also permits locking to be
974  * deferred until after construction of the lock object. Note that
975  * only one thread may call the methods of any one RecMutex::TrackLock
976  * object, including causing its destructor to be invoked.
977  */
978 
980  RecMutex& mutex;
981  bool owner;
982 
983 public:
984 
985 /**
986  * This class cannot be copied. The copy constructor is deleted.
987  */
988  TrackLock(const RecMutex::TrackLock&) = delete;
989 
990 /**
991  * This class cannot be copied. The assignment operator is deleted.
992  */
994 
995 /**
996  * This calls RecMutex::lock(), and so locks the mutex and acquires
997  * ownership. It blocks if the mutex is already locked until the
998  * mutex becomes free, unless the calling thread already holds the
999  * lock, in which case it increments the lock count and returns
1000  * immediately. This method should normally only be called if a
1001  * previous call has been made to RecMutex::TrackLock::unlock() or
1002  * this RecMutex::TrackLock object has been constructed with the
1003  * Thread::defer enum tag. It is not a cancellation point. It does
1004  * not throw.
1005  * @return 0 if successful, otherwise the pthread mutex error number.
1006  * @note With this library implementation, the only pthread error
1007  * number which could be returned by this method is EAGAIN, which it
1008  * would do if the maximum recursive lock count for the particular
1009  * mutex in question has been reached. Usually this number is at or
1010  * around INT_MAX and hence the return value is usually not worth
1011  * checking for except during debugging.
1012  */
1013  int lock() noexcept {int ret = mutex.lock(); if (!owner) owner = !ret; return ret;}
1014 
1015 /**
1016  * This calls RecMutex::trylock(), and so tries to lock the mutex and
1017  * acquire ownership, but returns immediately if it is already locked
1018  * with value EBUSY unless the calling thread already holds the lock,
1019  * in which case it returns normally and increments the lock count.
1020  * This method should normally only be called if a previous call has
1021  * been made to RecMutex::TrackLock::unlock() or this
1022  * RecMutex::TrackLock object has been constructed with the
1023  * Thread::defer enum tag. It is not a cancellation point. It does
1024  * not throw.
1025  * @return 0 if successful, otherwise EBUSY or other pthread mutex
1026  * error number.
1027  * @note With this library implementation, apart from EBUSY, the only
1028  * other pthread error number which could be returned by this method
1029  * is EAGAIN, which it would do if the maximum recursive lock count
1030  * for the particular mutex in question has been reached. Usually
1031  * this number is at or around INT_MAX and hence an EAGAIN error
1032  * return value is usually not worth checking for except during
1033  * debugging.
1034  */
1035  int trylock() noexcept {int ret = mutex.trylock(); if (!owner) owner = !ret; return ret;}
1036 
1037 /**
1038  * This calls RecMutex::unlock(), and so unlocks a locked mutex owned
1039  * by the calling thread, or decrements the lock count (if it has been
1040  * recursively locked). It will cause is_owner() to return false
1041  * unless a subsequent call is made to lock() or a subsequent
1042  * successful call is made to trylock(). It is not a cancellation
1043  * point. It does not throw.
1044  * @return 0 if successful, otherwise the pthread mutex error number.
1045  * @note With this library implementation, the only pthread error
1046  * number which could be returned by this method is EPERM because the
1047  * calling thread does not own the particular mutex in question
1048  * (however POSIX does not require that return value in that case and
1049  * hence the return value is usually not worth checking for except
1050  * during debugging).
1051  */
1052  int unlock() noexcept {int ret = mutex.unlock(); if (owner) owner = ret; return ret;}
1053 
1054 /**
1055  * Indicates whether the mutex managed by this Mutex::TrackLock object
1056  * is locked by it (whether originally or recursively) and so owned by
1057  * it. It does not throw.
1058  * @return true if the mutex is owned by this object, otherwise false.
1059  */
1060  bool is_owner() const noexcept {return owner;}
1061 
1062 /**
1063  * This constructor locks the mutex passed to it. See
1064  * RecMutex::lock() for a description of the outcomes. It is not a
1065  * cancellation point. It does not throw.
1066  * @param mutex_ The mutex to be locked.
1067  * @exception Cgu::Thread::RecMutexError Throws this exception if
1068  * initialization of the mutex fails because the maximum recursive
1069  * lock count for the particular mutex in question has been reached.
1070  * Usually this number is at or around INT_MAX so it is not usually
1071  * useful to check for it except during debugging.
1072  */
1073  TrackLock(RecMutex& mutex_): mutex(mutex_), owner(true) {if (mutex.lock()) throw RecMutexError();}
1074 
1075 /**
1076  * This constructor takes an already locked mutex (say as a result of
1077  * RecMutex::trylock()), and takes ownership of it. It is not a
1078  * cancellation point. It does not throw.
1079  * @param mutex_ The mutex to be managed by this object.
1080  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
1081  */
1082  TrackLock(RecMutex& mutex_, Locked tag) noexcept: mutex(mutex_), owner(true) {}
1083 
1084 /**
1085  * This constructor defers locking of the mutex (and so taking
1086  * ownership of it) until an explicit call to lock() or trylock() is
1087  * made. It is not a cancellation point. It does not throw.
1088  * @param mutex_ The mutex to be managed by this object.
1089  * @param tag Pass the Cgu::Thread::defer enum tag to this parameter.
1090  */
1091  TrackLock(RecMutex& mutex_, DeferLock tag) noexcept: mutex(mutex_), owner(false) {}
1092 
1093 /**
1094  * This class requires initialisation with a RecMutex. The default
1095  * constructor is deleted.
1096  */
1097  TrackLock() = delete;
1098 
1099 /**
1100  * The destructor unlocks the managed mutex if it is owned by this
1101  * RecMutex::TrackLock object. See RecMutex::unlock() for a
1102  * description of the outcomes if it is so owned. It is not a
1103  * cancellation point. It does not throw.
1104  */
1105  ~TrackLock() {if (owner) mutex.unlock();}
1106 
1107 /* Only has effect if --with-glib-memory-slices-compat or
1108  * --with-glib-memory-slices-no-compat option picked */
1110 };
1111 
1112 /**
1113  * @class GrecmutexLock mutex.h c++-gtk-utils/mutex.h
1114  * @brief A scoped locking class for exception safe locking of
1115  * GStaticRecMutex objects.
1116  * @details This class is mainly intended for use where the native
1117  * pthreads implementation does not support recursive mutexes so
1118  * Cgu::Thread::RecMutex and Cgu::Thread::RecMutex::Lock cannot be
1119  * used.
1120  *
1121  * It should be noted that this class is for use with GStaticRecMutex
1122  * objects, and not the GRecMutex objects available in glib from glib
1123  * version 2.32. If glib >= 2.32 is installed, it can be assumed that
1124  * native recursive mutexes and so Cgu::Thread::RecMutex are
1125  * available, as glib >= 2.32 also uses native recursive mutexes.
1126  */
1128  GStaticRecMutex& mutex;
1129 public:
1130 
1131 /**
1132  * This class cannot be copied. The copy constructor is deleted.
1133  */
1134  GrecmutexLock(const GrecmutexLock&) = delete;
1135 
1136 /**
1137  * This class cannot be copied. The assignment operator is deleted.
1138  */
1139  GrecmutexLock& operator=(const GrecmutexLock&) = delete;
1140 
1141 /**
1142  * This method provides access to the GStaticRecMutex object locked by
1143  * this GrecmutexLock object. It does not throw. It is thread safe.
1144  * @return A pointer to the GStaticRecMutex object.
1145  */
1146  GStaticRecMutex* get() const noexcept {return &mutex;}
1147 /**
1148  * This constructor locks the mutex and acquires ownership, and blocks
1149  * if it is already locked until it becomes free, unless the
1150  * constructing thread already holds the lock, in which case it
1151  * increments the lock count and returns immediately. It is not a
1152  * cancellation point. It does not throw.
1153  * @param mutex_ The mutex to be locked.
1154  */
1155  // this is not inline, so we can apply GLIB_VERSION_MIN_REQUIRED
1156  GrecmutexLock(GStaticRecMutex& mutex_);
1157 
1158 /**
1159  * This constructor takes an already locked mutex (say as a result of
1160  * g_static_rec_mutex_trylock()), and takes ownership of it. It is not a
1161  * cancellation point. It does not throw.
1162  * @param mutex_ The mutex to be managed by this object.
1163  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
1164  */
1165  GrecmutexLock(GStaticRecMutex& mutex_, Locked tag): mutex(mutex_) {}
1166 
1167 /**
1168  * This class requires initialisation with a GStaticRecMutex. The
1169  * default constructor is deleted.
1170  */
1171  GrecmutexLock() = delete;
1172 
1173 /**
1174  * The destructor unlocks the owned mutex, and either relinquishes
1175  * ownership (if the mutex has not been recursively locked) or
1176  * decrements the lock count (if it has). It is not a cancellation
1177  * point. It does not throw.
1178  */
1179  // this is not inline, so we can apply GLIB_VERSION_MIN_REQUIRED
1180  ~GrecmutexLock();
1181 
1182 /* Only has effect if --with-glib-memory-slices-compat or
1183  * --with-glib-memory-slices-no-compat option picked */
1185 };
1186 
1187 } // namespace Thread
1188 
1189 } // namespace Cgu
1190 
1191 #endif
int lock() noexcept
Definition: mutex.h:147
int trylock() noexcept
Definition: mutex.h:376
RecMutex::Lock & operator=(const RecMutex::Lock &)=delete
virtual const char * what() const
Definition: mutex.h:82
int trylock() noexcept
Definition: mutex.h:889
int timed_wait(Mutex::Lock &lock, const timespec &abs_time)
Definition: mutex.h:593
Mutex & operator=(const Mutex &)=delete
Lock(Mutex &mutex_) noexcept
Definition: mutex.h:284
virtual const char * what() const
Definition: mutex.h:86
Definition: mutex.h:199
Definition: mutex.h:85
A scoped locking class for exception safe RecMutex locking which tracks the status of its mutex...
Definition: mutex.h:979
static int test_support()
int unlock() noexcept
Definition: mutex.h:170
int trylock() noexcept
Definition: mutex.h:255
TrackLock(RecMutex &mutex_, DeferLock tag) noexcept
Definition: mutex.h:1091
A wrapper class for pthread condition variables.
Definition: mutex.h:449
int unlock() noexcept
Definition: mutex.h:277
int lock() noexcept
Definition: mutex.h:866
int trylock() noexcept
Definition: mutex.h:1035
Lock(Mutex &mutex_, Locked tag) noexcept
Definition: mutex.h:293
~Lock()
Definition: mutex.h:305
~TrackLock()
Definition: mutex.h:1105
A scoped locking class for exception safe RecMutex locking.
Definition: mutex.h:832
Definition: mutex.h:196
int timed_wait(Mutex::TrackLock &lock, const timespec &abs_time)
Definition: mutex.h:607
TrackLock(Mutex &mutex_, DeferLock tag) noexcept
Definition: mutex.h:424
static void get_abs_time(timespec &ts, unsigned int millisec)
static bool have_monotonic_clock()
TrackLock(Mutex &mutex_) noexcept
Definition: mutex.h:406
int lock() noexcept
Definition: mutex.h:1013
RecMutex::TrackLock & operator=(const RecMutex::TrackLock &)=delete
A scoped locking class for exception safe Mutex locking.
Definition: mutex.h:207
Mutex::Lock & operator=(const Mutex::Lock &)=delete
~TrackLock()
Definition: mutex.h:436
Lock(RecMutex &mutex_)
Definition: mutex.h:929
int trylock() noexcept
Definition: mutex.h:157
int timed_wait(Mutex &mutex, const timespec &abs_time)
Definition: mutex.h:578
A wrapper class for pthread mutexes.
Definition: mutex.h:117
TrackLock(RecMutex &mutex_)
Definition: mutex.h:1073
GrecmutexLock & operator=(const GrecmutexLock &)=delete
bool is_owner() const noexcept
Definition: mutex.h:1060
Mutex()
Definition: mutex.h:179
Definition: application.h:44
TrackLock(Mutex &mutex_, Locked tag) noexcept
Definition: mutex.h:415
int unlock() noexcept
Definition: mutex.h:916
Definition: mutex.h:66
A scoped locking class for exception safe Mutex locking which tracks the status of its mutex...
Definition: mutex.h:331
bool is_owner() const noexcept
Definition: mutex.h:399
int trylock() noexcept
Definition: mutex.h:750
Locked
Definition: mutex.h:196
DeferLock
Definition: mutex.h:199
int unlock() noexcept
Definition: mutex.h:1052
A scoped locking class for exception safe locking of GStaticRecMutex objects.
Definition: mutex.h:1127
int signal() noexcept
Definition: mutex.h:472
int wait(Mutex::TrackLock &lock)
Definition: mutex.h:537
int broadcast() noexcept
Definition: mutex.h:483
~Cond(void)
Definition: mutex.h:663
RecMutex & operator=(const RecMutex &)=delete
A wrapper class for pthread mutexes which provides a recursive mutex.
Definition: mutex.h:702
~RecMutex()
Definition: mutex.h:819
Mutex::TrackLock & operator=(const Mutex::TrackLock &)=delete
virtual const char * what() const
Definition: mutex.h:67
TrackLock(RecMutex &mutex_, Locked tag) noexcept
Definition: mutex.h:1082
Lock(RecMutex &mutex_, Locked tag) noexcept
Definition: mutex.h:938
int lock() noexcept
Definition: mutex.h:240
int unlock() noexcept
Definition: mutex.h:765
int unlock() noexcept
Definition: mutex.h:391
int lock() noexcept
Definition: mutex.h:733
int wait(Mutex::Lock &lock)
Definition: mutex.h:525
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Cond & operator=(const Cond &)=delete
~Mutex()
Definition: mutex.h:187
int lock() noexcept
Definition: mutex.h:363
GrecmutexLock(GStaticRecMutex &mutex_, Locked tag)
Definition: mutex.h:1165
~Lock()
Definition: mutex.h:951
Definition: mutex.h:81
int wait(Mutex &mutex)
Definition: mutex.h:513