c++-gtk-utils

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

- File List
- File Members

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>
47 #include <c++-gtk-utils/cgu_config.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
190 CGU_GLIB_MEMORY_SLICES_FUNCS
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
199 enum DeferLock {defer};
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 */
309 CGU_GLIB_MEMORY_SLICES_FUNCS
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
331 class Mutex::TrackLock {
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 */
440 CGU_GLIB_MEMORY_SLICES_FUNCS
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 */
593 int timed_wait(Mutex::Lock& lock,
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 */
607 int timed_wait(Mutex::TrackLock& lock,
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 */
667 CGU_GLIB_MEMORY_SLICES_FUNCS
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 */
823 CGU_GLIB_MEMORY_SLICES_FUNCS
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
832 class RecMutex::Lock {
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 */
955 CGU_GLIB_MEMORY_SLICES_FUNCS
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
979 class RecMutex::TrackLock {
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 */
993 RecMutex::TrackLock& operator=(const RecMutex::TrackLock&) = delete;
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 */
1109 CGU_GLIB_MEMORY_SLICES_FUNCS
1110 };
1111
1112 // we don't want glib's warnings about GStaticRecMutex
1113 #ifdef CGU_USE_DIAGNOSTIC_PRAGMAS
1114 #pragma GCC diagnostic push
1115 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1116 #endif
1117
1118 /**
1119 * @class GrecmutexLock mutex.h c++-gtk-utils/mutex.h
1120 * @brief A scoped locking class for exception safe locking of
1121 * GStaticRecMutex objects.
1122 * @details This class is mainly intended for use where the native
1123 * pthreads implementation does not support recursive mutexes so
1124 * Cgu::Thread::RecMutex and Cgu::Thread::RecMutex::Lock cannot be
1125 * used.
1126 *
1127 * It should be noted that this class is for use with GStaticRecMutex
1128 * objects, and not the GRecMutex objects available in glib from glib
1129 * version 2.32. If glib >= 2.32 is installed, it can be assumed that
1130 * native recursive mutexes and so Cgu::Thread::RecMutex are
1131 * available, as glib >= 2.32 also uses native recursive mutexes.
1132 */
1133 class GrecmutexLock {
1134 GStaticRecMutex& mutex;
1135 public:
1136
1137 /**
1138 * This class cannot be copied. The copy constructor is deleted.
1139 */
1140 GrecmutexLock(const GrecmutexLock&) = delete;
1141
1142 /**
1143 * This class cannot be copied. The assignment operator is deleted.
1144 */
1145 GrecmutexLock& operator=(const GrecmutexLock&) = delete;
1146
1147 /**
1148 * This method provides access to the GStaticRecMutex object locked by
1149 * this GrecmutexLock object. It does not throw. It is thread safe.
1150 * @return A pointer to the GStaticRecMutex object.
1151 */
1152 GStaticRecMutex* get() const noexcept {return &mutex;}
1153 /**
1154 * This constructor locks the mutex and acquires ownership, and blocks
1155 * if it is already locked until it becomes free, unless the
1156 * constructing thread already holds the lock, in which case it
1157 * increments the lock count and returns immediately. It is not a
1158 * cancellation point. It does not throw.
1159 * @param mutex_ The mutex to be locked.
1160 */
1161 // this is not inline, so we can apply GLIB_VERSION_MIN_REQUIRED
1162 GrecmutexLock(GStaticRecMutex& mutex_);
1163
1164 /**
1165 * This constructor takes an already locked mutex (say as a result of
1166 * g_static_rec_mutex_trylock()), and takes ownership of it. It is not a
1167 * cancellation point. It does not throw.
1168 * @param mutex_ The mutex to be managed by this object.
1169 * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
1170 */
1171 GrecmutexLock(GStaticRecMutex& mutex_, Locked tag): mutex(mutex_) {}
1172
1173 /**
1174 * This class requires initialisation with a GStaticRecMutex. The
1175 * default constructor is deleted.
1176 */
1177 GrecmutexLock() = delete;
1178
1179 /**
1180 * The destructor unlocks the owned mutex, and either relinquishes
1181 * ownership (if the mutex has not been recursively locked) or
1182 * decrements the lock count (if it has). It is not a cancellation
1183 * point. It does not throw.
1184 */
1185 // this is not inline, so we can apply GLIB_VERSION_MIN_REQUIRED
1186 ~GrecmutexLock();
1187
1188 /* Only has effect if --with-glib-memory-slices-compat or
1189 * --with-glib-memory-slices-no-compat option picked */
1190 CGU_GLIB_MEMORY_SLICES_FUNCS
1191 };
1192
1193 #ifdef CGU_USE_DIAGNOSTIC_PRAGMAS
1194 #pragma GCC diagnostic pop
1195 #endif
1196
1197 } // namespace Thread
1198
1199 } // namespace Cgu
1200
1201 #endif
Cgu::Thread::RecMutex::TrackLock::unlock
int unlock() noexcept
Definition: mutex.h:1052
Cgu::Thread::Cond::get_abs_time
static void get_abs_time(timespec &ts, unsigned int millisec)
Cgu::Thread::Mutex::TrackLock::lock
int lock() noexcept
Definition: mutex.h:363
Cgu::Thread::Cond::timed_wait
int timed_wait(Mutex &mutex, const timespec &abs_time)
Definition: mutex.h:578
Cgu::Thread::RecMutex::TrackLock::is_owner
bool is_owner() const noexcept
Definition: mutex.h:1060
Cgu::Thread::RecMutex::TrackLock::lock
int lock() noexcept
Definition: mutex.h:1013
Cgu
Definition: application.h:44
Cgu::Thread::RecMutex::TrackLock::~TrackLock
~TrackLock()
Definition: mutex.h:1105
Cgu::Thread::Cond::wait
int wait(Mutex::Lock &lock)
Definition: mutex.h:525
Cgu::Thread::RecMutex::Lock::trylock
int trylock() noexcept
Definition: mutex.h:889
Cgu::Thread::Mutex::lock
int lock() noexcept
Definition: mutex.h:147
Cgu::Thread::Cond::Cond
Cond()
Cgu::Thread::locked
@ locked
Definition: mutex.h:196
Cgu::Thread::Mutex::TrackLock::TrackLock
TrackLock()=delete
Cgu::Thread::Cond::have_monotonic_clock
static bool have_monotonic_clock()
Cgu::Thread::RecMutex
A wrapper class for pthread mutexes which provides a recursive mutex.
Definition: mutex.h:702
Cgu::Thread::GrecmutexLock::GrecmutexLock
GrecmutexLock()=delete
Cgu::Thread::Mutex::unlock
int unlock() noexcept
Definition: mutex.h:170
Cgu::Thread::RecMutex::Lock
A scoped locking class for exception safe RecMutex locking.
Definition: mutex.h:832
Cgu::Thread::Cond::wait
int wait(Mutex::TrackLock &lock)
Definition: mutex.h:537
Cgu::Thread::Cond::broadcast
int broadcast() noexcept
Definition: mutex.h:483
Cgu::Thread::Mutex::Lock::~Lock
~Lock()
Definition: mutex.h:305
Cgu::Thread::RecMutex::test_support
static int test_support()
Cgu::Thread::RecMutex::trylock
int trylock() noexcept
Definition: mutex.h:750
Cgu::Thread::CondError::what
virtual const char * what() const
Definition: mutex.h:67
Cgu::Thread::RecMutex::Lock::operator=
RecMutex::Lock & operator=(const RecMutex::Lock &)=delete
Cgu::Thread::Cond::timed_wait
int timed_wait(Mutex::TrackLock &lock, const timespec &abs_time)
Definition: mutex.h:607
Cgu::Thread::Cond
A wrapper class for pthread condition variables.
Definition: mutex.h:449
Cgu::Thread::RecMutex::TrackLock::TrackLock
TrackLock()=delete
Cgu::Thread::RecMutex::lock
int lock() noexcept
Definition: mutex.h:733
Cgu::Thread::Mutex::TrackLock::trylock
int trylock() noexcept
Definition: mutex.h:376
Cgu::Thread::Mutex::TrackLock::TrackLock
TrackLock(Mutex &mutex_, DeferLock tag) noexcept
Definition: mutex.h:424
Cgu::Thread::Cond::timed_wait
int timed_wait(Mutex::Lock &lock, const timespec &abs_time)
Definition: mutex.h:593
Cgu::Thread::Mutex::Lock::Lock
Lock(Mutex &mutex_) noexcept
Definition: mutex.h:284
Cgu::Thread::Mutex::TrackLock::~TrackLock
~TrackLock()
Definition: mutex.h:436
Cgu::Thread::RecMutex::Lock::unlock
int unlock() noexcept
Definition: mutex.h:916
Cgu::Thread::RecMutex::operator=
RecMutex & operator=(const RecMutex &)=delete
Cgu::Thread::Mutex::~Mutex
~Mutex()
Definition: mutex.h:187
Cgu::Thread::Cond::~Cond
~Cond(void)
Definition: mutex.h:663
Cgu::Thread::RecMutex::TrackLock::TrackLock
TrackLock(RecMutex &mutex_, Locked tag) noexcept
Definition: mutex.h:1082
Cgu::Thread::GrecmutexLock::GrecmutexLock
GrecmutexLock(GStaticRecMutex &mutex_, Locked tag)
Definition: mutex.h:1171
Cgu::Thread::RecMutex::Lock::Lock
Lock(RecMutex &mutex_)
Definition: mutex.h:929
Cgu::Thread::Mutex::TrackLock
A scoped locking class for exception safe Mutex locking which tracks the status of its mutex.
Definition: mutex.h:331
Cgu::Thread::GrecmutexLock::operator=
GrecmutexLock & operator=(const GrecmutexLock &)=delete
Cgu::Thread::Cond::wait
int wait(Mutex &mutex)
Definition: mutex.h:513
Cgu::Thread::GrecmutexLock::~GrecmutexLock
~GrecmutexLock()
Cgu::Thread::Mutex::Lock::lock
int lock() noexcept
Definition: mutex.h:240
Cgu::Thread::Mutex::trylock
int trylock() noexcept
Definition: mutex.h:157
Cgu::Thread::RecMutex::TrackLock
A scoped locking class for exception safe RecMutex locking which tracks the status of its mutex.
Definition: mutex.h:979
Cgu::Thread::Mutex::TrackLock::TrackLock
TrackLock(Mutex &mutex_) noexcept
Definition: mutex.h:406
Cgu::Thread::Cond::operator=
Cond & operator=(const Cond &)=delete
Cgu::Thread::defer
@ defer
Definition: mutex.h:199
Cgu::Thread::GrecmutexLock::get
GStaticRecMutex * get() const noexcept
Definition: mutex.h:1152
Cgu::Thread::Cond::signal
int signal() noexcept
Definition: mutex.h:472
Cgu::Thread::DeferLock
DeferLock
Definition: mutex.h:199
Cgu::Thread::Mutex::Lock
A scoped locking class for exception safe Mutex locking.
Definition: mutex.h:207
Cgu::Thread::Mutex::TrackLock::TrackLock
TrackLock(Mutex &mutex_, Locked tag) noexcept
Definition: mutex.h:415
Cgu::Thread::Mutex::Lock::operator=
Mutex::Lock & operator=(const Mutex::Lock &)=delete
Cgu::Thread::RecMutex::Lock::Lock
Lock(RecMutex &mutex_, Locked tag) noexcept
Definition: mutex.h:938
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Cgu::Thread::RecMutex::Lock::Lock
Lock()=delete
Cgu::Thread::RecMutex::TrackLock::TrackLock
TrackLock(RecMutex &mutex_, DeferLock tag) noexcept
Definition: mutex.h:1091
Cgu::Thread::Mutex::Lock::unlock
int unlock() noexcept
Definition: mutex.h:277
Cgu::Thread::GrecmutexLock
A scoped locking class for exception safe locking of GStaticRecMutex objects.
Definition: mutex.h:1133
Cgu::Thread::Locked
Locked
Definition: mutex.h:196
Cgu::Thread::RecMutexError::what
virtual const char * what() const
Definition: mutex.h:86
Cgu::Thread::Mutex::Lock::trylock
int trylock() noexcept
Definition: mutex.h:255
Cgu::Thread::RecMutex::TrackLock::trylock
int trylock() noexcept
Definition: mutex.h:1035
Cgu::Thread::RecMutex::TrackLock::operator=
RecMutex::TrackLock & operator=(const RecMutex::TrackLock &)=delete
Cgu::Thread::RecMutexError
Definition: mutex.h:85
Cgu::Thread::MutexError::what
virtual const char * what() const
Definition: mutex.h:82
Cgu::Thread::Mutex::TrackLock::unlock
int unlock() noexcept
Definition: mutex.h:391
Cgu::Thread::RecMutex::RecMutex
RecMutex()
Cgu::Thread::Mutex::operator=
Mutex & operator=(const Mutex &)=delete
Cgu::Thread::RecMutex::~RecMutex
~RecMutex()
Definition: mutex.h:819
Cgu::Thread::CondError
Definition: mutex.h:66
Cgu::Thread::RecMutex::Lock::lock
int lock() noexcept
Definition: mutex.h:866
Cgu::Thread::Mutex::TrackLock::is_owner
bool is_owner() const noexcept
Definition: mutex.h:399
Cgu::Thread::MutexError
Definition: mutex.h:81
Cgu::Thread::Mutex::Lock::Lock
Lock()=delete
Cgu::Thread::RecMutex::unlock
int unlock() noexcept
Definition: mutex.h:765
Cgu::Thread::Mutex::Mutex
Mutex()
Definition: mutex.h:179
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:117
Cgu::Thread::Mutex::Lock::Lock
Lock(Mutex &mutex_, Locked tag) noexcept
Definition: mutex.h:293
cgu_config.h
Cgu::Thread::RecMutex::Lock::~Lock
~Lock()
Definition: mutex.h:951
Cgu::Thread::Mutex::TrackLock::operator=
Mutex::TrackLock & operator=(const Mutex::TrackLock &)=delete
Cgu::Thread::RecMutex::TrackLock::TrackLock
TrackLock(RecMutex &mutex_)
Definition: mutex.h:1073