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