c++-gtk-utils
mutex.h
Go to the documentation of this file.
00001 /* Copyright (C) 2005 to 2011 Chris Vine
00002 
00003 The library comprised in this file or of which this file is part is
00004 distributed by Chris Vine under the GNU Lesser General Public
00005 License as follows:
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public License
00009    as published by the Free Software Foundation; either version 2.1 of
00010    the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License, version 2.1, for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License, version 2.1, along with this library (see the file LGPL.TXT
00019    which came with this source code package in the c++-gtk-utils
00020    sub-directory); if not, write to the Free Software Foundation, Inc.,
00021    59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA.
00022 
00023 However, it is not intended that the object code of a program whose
00024 source code instantiates a template from this file or uses macros or
00025 inline functions (of any length) should by reason only of that
00026 instantiation or use be subject to the restrictions of use in the GNU
00027 Lesser General Public License.  With that in mind, the words "and
00028 macros, inline functions and instantiations of templates (of any
00029 length)" shall be treated as substituted for the words "and small
00030 macros and small inline functions (ten lines or less in length)" in
00031 the fourth paragraph of section 5 of that licence.  This does not
00032 affect any other reason why object code may be subject to the
00033 restrictions in that licence (nor for the avoidance of doubt does it
00034 affect the application of section 2 of that licence to modifications
00035 of the source code in this file).
00036 
00037 */
00038 
00039 #ifndef CGU_MUTEX_H
00040 #define CGU_MUTEX_H
00041 
00042 #include <exception>
00043 #include <pthread.h>
00044 #include <time.h>
00045 
00046 #include <glib.h>
00047 #include <c++-gtk-utils/cgu_config.h>
00048 
00049 /**
00050  * @file mutex.h
00051  * @brief Provides wrapper classes for pthread mutexes and condition
00052  * variables, and scoped locking classes for exception safe mutex
00053  * locking.
00054  * @note If the system supports monotonic clocks (and this library is
00055  * not being cross-compiled onto a different architecture), then a
00056  * system monotonic clock will be used in
00057  * Cgu::Thread::Cond::timed_wait() and
00058  * Cgu::Thread::Cond::get_abs_time().  This can be tested at run time
00059  * with Cgu::Thread::Cond::have_monotonic_clock().
00060  */
00061 
00062 namespace Cgu {
00063 
00064 namespace Thread {
00065 
00066 struct CondError: public std::exception {
00067   virtual const char* what() const throw() {return "Thread::CondError";}
00068 };
00069 
00070 /*
00071  * Since version 1.2.0, which automatically checks for monotonic
00072  * clocks in its configure script, this exception is no longer thrown.
00073  * We keep the class just for source compatibility purposes.
00074  */
00075 #ifndef DOXYGEN_PARSING
00076 struct CondSetClockError: public std::exception {
00077   virtual const char* what() const throw() {return "Thread::CondSetClockError";}
00078 };
00079 #endif
00080 
00081 struct MutexError: public std::exception {
00082   virtual const char* what() const throw() {return "Thread::MutexError";}
00083 };
00084 
00085 struct RecMutexError: public std::exception {
00086   virtual const char* what() const throw() {return "Thread::RecMutexError";}
00087 };
00088 
00089 class Cond;
00090 
00091 /**
00092  * @class Mutex mutex.h c++-gtk-utils/mutex.h
00093  * @brief A wrapper class for pthread mutexes.
00094  * @sa Thread::Thread Thread::Mutex::Lock Thread::Mutex::TrackLock Thread::Cond Thread::RecMutex
00095  *
00096  * This class can be used interchangeably with threads started with
00097  * GThread and by this library, as both glib and this library use
00098  * pthreads underneath on POSIX and other unix-like OSes.  It can also
00099  * be used interchangeably with those started by C++11 and with
00100  * std::mutex and similar objects, as in C++11 on unix-like OSes these
00101  * facilities will be built on top of pthreads (for which purpose
00102  * C++11 provides the std::native_handle_type type and
00103  * std::thread::native_handle() function), or if they are not, they
00104  * will use the same threading primitives provided by the kernel.
00105  *
00106  * Unlike with GMutex, there is no separate class for static mutexes.
00107  * That is not necessary, as these Mutex objects can be constructed
00108  * statically as well as dynamically and there is no need to call
00109  * g_thread_init() before they are constructed.  (If created as a
00110  * static object in global scope, it will not be possible to catch
00111  * Thread::MutexError thrown by its constructor, but if a static
00112  * global mutex throws there is nothing that could be done anyway
00113  * except abort, and it would show that the pthreads installation is
00114  * seriously defective.)
00115  */
00116 
00117 class Mutex {
00118   pthread_mutex_t pthr_mutex;
00119   
00120 public:
00121   class Lock;
00122   class TrackLock;
00123   friend class Cond;
00124 
00125 /**
00126  * This class cannot be copied.  The copy constructor is deleted.
00127  */
00128   Mutex(const Mutex&) = delete;
00129 
00130 /**
00131  * This class cannot be copied.  The assignment operator is deleted.
00132  */
00133   Mutex& operator=(const Mutex&) = delete;
00134 
00135 /**
00136  * Locks the mutex and acquires ownership.  Blocks if already locked
00137  * until it becomes free.  It is not a cancellation point.  It does
00138  * not throw.  It is thread safe.
00139  * @return 0 if successful, otherwise the pthread mutex error number.
00140  * @note With this library implementation, the only pthread error
00141  * number which could be returned by this method is EDEADLK, which it
00142  * would do if the default pthread mutex behaviour happens to return
00143  * that error rather than deadlock in the case of recursive locking.
00144  * Most default implementations do not do this and hence the return
00145  * value is usually not worth checking for except during debugging.
00146  */
00147   int lock() {return pthread_mutex_lock(&pthr_mutex);}
00148 
00149 /**
00150  * Tries to lock the mutex and acquire ownership, but returns
00151  * immediately if it is already locked with value EBUSY.  It is not a
00152  * cancellation point.  It does not throw.  It is thread safe.
00153  * @return 0 if successful, otherwise EBUSY.
00154  * @note With this library implementation, the only pthread error
00155  * number which could be returned by this method is EBUSY.
00156  */
00157   int trylock() {return pthread_mutex_trylock(&pthr_mutex);}
00158 
00159 /**
00160  * Unlocks a locked mutex owned by the calling thread and relinquishes
00161  * ownership.  It is not a cancellation point.  It does not throw.  It
00162  * must be called by the thread which owns the mutex.
00163  * @return 0 if successful, otherwise the pthread mutex error number.
00164  * @note With this library implementation, the only pthread error
00165  * number which could be returned by this method is EPERM because the
00166  * calling thread does not own the mutex (however POSIX does not
00167  * require that return value in that case and hence the return value
00168  * is usually not worth checking for except during debugging).
00169  */
00170   int unlock() {return pthread_mutex_unlock(&pthr_mutex);}
00171 
00172 /**
00173  * Initialises the pthread mutex.  It is not a cancellation point.
00174  * @exception Cgu::Thread::MutexError Throws this exception if
00175  * initialization of the mutex fails.  (It is often not worth checking
00176  * for this, as it means either memory is exhausted or pthread has run
00177  * out of other resources to create new mutexes.)
00178  */
00179   Mutex() {if (pthread_mutex_init(&pthr_mutex, 0)) throw MutexError();}
00180 
00181 /**
00182  *  Destroys the pthread mutex.  It is not a cancellation point.  It
00183  *  does not throw.
00184  */
00185   ~Mutex() {pthread_mutex_destroy(&pthr_mutex);}
00186 
00187 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
00188   CGU_GLIB_MEMORY_SLICES_FUNCS
00189 #endif
00190 };
00191 
00192 // used as a second argument to Lock::Lock() and TrackLock::TrackLock
00193 // in cases where the mutex has already been locked (say by Mutex::trylock())
00194 enum Locked {locked};
00195 // used as a second argument to TrackLock::TrackLock() in cases where
00196 // locking of the mutex is to be deferred
00197 enum DeferLock {defer};
00198 
00199 /**
00200  * @class Mutex::Lock mutex.h c++-gtk-utils/mutex.h
00201  * @brief A scoped locking class for exception safe Mutex locking.
00202  * @sa Thread::Mutex Thread::Mutex::TrackLock Thread::Thread Thread::Cond
00203  */
00204 
00205 class Mutex::Lock {
00206   Mutex& mutex;
00207 
00208 public:
00209   friend class Cond;
00210 
00211 /**
00212  * This class cannot be copied.  The copy constructor is deleted.
00213  */
00214   Lock(const Mutex::Lock&) = delete;
00215 
00216 /**
00217  * This class cannot be copied.  The assignment operator is deleted.
00218  */
00219   Mutex::Lock& operator=(const Mutex::Lock&) = delete;
00220 
00221 /**
00222  * Calls Mutex::lock(), and so locks the mutex and reacquires
00223  * ownership.  It blocks if the mutex is already locked until the
00224  * mutex becomes free.  This method should normally only be called if
00225  * a previous call has been made to Mutex::Lock::unlock() (that is,
00226  * where the thread owning the Mutex::Lock object has temporarily
00227  * allowed another thread to take the mutex concerned).  It is not a
00228  * cancellation point.  It does not throw.
00229  * @return 0 if successful, otherwise the pthread mutex error number.
00230  * @note With this library implementation, the only pthread error
00231  * number which could be returned by this method is EDEADLK, which it
00232  * would do if the default pthread mutex behaviour happens to return
00233  * that error rather than deadlock in the case of recursive locking.
00234  * Most default implementations do not do this and hence the return
00235  * value is usually not worth checking for except during debugging.
00236  * @sa Mutex::TrackLock.
00237  */
00238   int lock() {return mutex.lock();}
00239 
00240 /**
00241  * Calls Mutex::trylock(), and so tries to lock the mutex and
00242  * reacquire ownership, but returns immediately if it is already
00243  * locked with value EBUSY.  This method should normally only be
00244  * called if a previous call has been made to Mutex::Lock::unlock()
00245  * (that is, where the thread owning the Mutex::Lock object has
00246  * temporarily allowed another thread to take the mutex concerned).
00247  * It is not a cancellation point.  It does not throw.
00248  * @return 0 if successful, otherwise EBUSY.
00249  * @note With this library implementation, the only pthread error
00250  * number which could be returned by this method is EBUSY.
00251  * @sa Mutex::TrackLock.
00252  */
00253   int trylock() {return mutex.trylock();}
00254 
00255 /**
00256  * Calls Mutex::unlock(), and so unlocks a locked mutex owned by the
00257  * calling thread and relinquishes ownership (so temporarily allowing
00258  * another thread to take the mutex).  This method should normally
00259  * only be called if it is to be followed by a call to
00260  * Mutex::Lock::lock() or a successful call to Mutex::Lock::trylock()
00261  * before the Mutex::Lock object concerned goes out of scope
00262  * (otherwise Mutex::Lock's destructor will attempt to unlock an
00263  * already unlocked mutex or a mutex of which another thread has by
00264  * then taken ownership - Mutex::Lock objects do not maintain state).
00265  * See Mutex::TrackLock::unlock() for a safe version of this method.
00266  * It is not a cancellation point.  It does not throw.
00267  * @return 0 if successful, otherwise the pthread mutex error number.
00268  * @note With this library implementation, the only pthread error
00269  * number which could be returned by this method is EPERM because the
00270  * calling thread does not own the mutex (however POSIX does not
00271  * require that return value in that case and hence the return value
00272  * is usually not worth checking for except during debugging).
00273  * @sa Mutex::TrackLock.
00274  */
00275   int unlock() {return mutex.unlock();}
00276 
00277 /**
00278  * This constructor locks the mutex passed to it.  It is not a
00279  * cancellation point.  It does not throw.
00280  * @param mutex_ The mutex to be locked.
00281  */
00282   Lock(Mutex& mutex_): mutex(mutex_) {mutex.lock();}
00283 
00284 /**
00285  * This constructor takes an already locked mutex (say as a result of
00286  * Mutex::trylock()), and takes ownership of it.  It is not a
00287  * cancellation point.  It does not throw.
00288  * @param mutex_ The mutex to be managed by this object.
00289  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
00290  */
00291   Lock(Mutex& mutex_, Locked tag): mutex(mutex_) {}
00292 
00293 /**
00294  * This class requires initialisation with a Mutex.  The default
00295  * constructor is deleted.
00296  */
00297   Lock() = delete;
00298 
00299 /**
00300  * The destructor unlocks the owned mutex.  It is not a cancellation
00301  * point.  It does not throw.
00302  */
00303   ~Lock() {mutex.unlock();}
00304 
00305 /* Only has effect if --with-glib-memory-slices-compat or
00306  * --with-glib-memory-slices-no-compat option picked */
00307   CGU_GLIB_MEMORY_SLICES_FUNCS
00308 };
00309 
00310 /**
00311  * @class Mutex::TrackLock mutex.h c++-gtk-utils/mutex.h
00312  * @brief A scoped locking class for exception safe Mutex locking
00313  * which tracks the status of its mutex.
00314  * @sa Thread::Mutex Thread::Mutex::Lock Thread::Thread Thread::Cond
00315  *
00316  * This class is similar to a Mutex::Lock object, except that it
00317  * tracks whether the mutex it manages is locked by the thread
00318  * creating the Mutex::TrackLock object (provided that, while the
00319  * Mutex::TrackLock object exists, the thread creating it only
00320  * accesses the mutex through that object).  This enables
00321  * Mutex::TrackLock::unlock() to be used without it being followed
00322  * later by a call to Mutex::TrackLock::lock() or a successful call to
00323  * Mutex::TrackLock::trylock(), and also permits locking to be
00324  * deferred until after construction of the lock object.  Note that
00325  * only one thread may call the methods of any one Mutex::TrackLock
00326  * object, including causing its destructor to be invoked.
00327  */
00328 
00329 class Mutex::TrackLock {
00330   Mutex& mutex;
00331   bool owner;
00332 
00333 public:
00334   friend class Cond;
00335 
00336 /**
00337  * This class cannot be copied.  The copy constructor is deleted.
00338  */
00339   TrackLock(const Mutex::TrackLock&) = delete;
00340 
00341 /**
00342  * This class cannot be copied.  The assignment operator is deleted.
00343  */
00344   Mutex::TrackLock& operator=(const Mutex::TrackLock&) = delete;
00345 
00346 /**
00347  * Calls Mutex::lock(), and so locks the mutex and acquires ownership.
00348  * It blocks if the mutex is already locked until the mutex becomes
00349  * free.  This method should normally only be called if a previous
00350  * call has been made to Mutex::TrackLock::unlock() or this
00351  * Mutex::TrackLock object has been constructed with the Thread::defer
00352  * enum tag.  It is not a cancellation point.  It does not throw.
00353  * @return 0 if successful, otherwise the pthread mutex error number.
00354  * @note With this library implementation, the only pthread error
00355  * number which could be returned by this method is EDEADLK, which it
00356  * would do if the default pthread mutex behaviour happens to return
00357  * that error rather than deadlock in the case of recursive locking.
00358  * Most default implementations do not do this and hence the return
00359  * value is usually not worth checking for except during debugging.
00360  */
00361   int lock() {int ret = mutex.lock(); if (!owner) owner = !ret; return ret;}
00362 
00363 /**
00364  * Calls Mutex::trylock(), and so tries to lock the mutex and acquire
00365  * ownership, but returns immediately if it is already locked with
00366  * value EBUSY.  This method should normally only be called if a
00367  * previous call has been made to Mutex::TrackLock::unlock() or this
00368  * Mutex::TrackLock object has been constructed with the Thread::defer
00369  * enum tag.  It is not a cancellation point.  It does not throw.
00370  * @return 0 if successful, otherwise EBUSY.
00371  * @note With this library implementation, the only pthread error
00372  * number which could be returned by this method is EBUSY.
00373  */
00374   int trylock() {int ret = mutex.trylock(); if (!owner) owner = !ret; return ret;}
00375 
00376 /**
00377  * Calls Mutex::unlock(), and so unlocks a locked mutex owned by the
00378  * calling thread.  It will cause is_owner() to return false unless a
00379  * subsequent call is made to lock() or a subsequent successful call
00380  * is made to trylock().  It is not a cancellation point.  It does not
00381  * throw.
00382  * @return 0 if successful, otherwise the pthread mutex error number.
00383  * @note With this library implementation, the only pthread error
00384  * number which could be returned by this method is EPERM because the
00385  * calling thread does not own the mutex (however POSIX does not
00386  * require that return value in that case and hence the return value
00387  * is usually not worth checking for except during debugging).
00388  */
00389   int unlock() {int ret = mutex.unlock(); if (owner) owner = ret; return ret;}
00390 
00391 /**
00392  * Indicates whether the mutex managed by this Mutex::TrackLock object
00393  * is locked, and so owned, by it.
00394  * @return true if the mutex is locked by this object, otherwise
00395  * false.
00396  */
00397   bool is_owner() const {return owner;}
00398 
00399 /**
00400  * This constructor locks the mutex passed to it.  It is not a
00401  * cancellation point.  It does not throw.
00402  * @param mutex_ The mutex to be locked.
00403  */
00404   TrackLock(Mutex& mutex_): mutex(mutex_), owner(true) {mutex.lock();}
00405 
00406 /**
00407  * This constructor takes an already locked mutex (say as a result of
00408  * Mutex::trylock()), and takes ownership of it.  It is not a
00409  * cancellation point.  It does not throw.
00410  * @param mutex_ The mutex to be managed by this object.
00411  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
00412  */
00413   TrackLock(Mutex& mutex_, Locked tag): mutex(mutex_), owner(true) {}
00414 
00415 /**
00416  * This constructor defers locking of the mutex (and so taking
00417  * ownership of it) until an explicit call to lock() or trylock() is
00418  * made.  It is not a cancellation point.  It does not throw.
00419  * @param mutex_ The mutex to be managed by this object.
00420  * @param tag Pass the Cgu::Thread::defer enum tag to this parameter.
00421  */
00422   TrackLock(Mutex& mutex_, DeferLock tag): mutex(mutex_), owner(false) {}
00423 
00424 /**
00425  * This class requires initialisation with a Mutex.  The default
00426  * constructor is deleted.
00427  */
00428   TrackLock() = delete;
00429 
00430 /**
00431  * The destructor unlocks the managed mutex if it is locked.  It is
00432  * not a cancellation point.  It does not throw.
00433  */
00434   ~TrackLock() {if (owner) mutex.unlock();}
00435 
00436 /* Only has effect if --with-glib-memory-slices-compat or
00437  * --with-glib-memory-slices-no-compat option picked */
00438   CGU_GLIB_MEMORY_SLICES_FUNCS
00439 };
00440 
00441 /**
00442  * @class Cond mutex.h c++-gtk-utils/mutex.h
00443  * @brief A wrapper class for pthread condition variables.
00444  * @sa Thread::Thread Thread::Mutex Thread::Mutex::Lock Thread::Mutex::TrackLock
00445  */
00446 
00447 class Cond {
00448   pthread_cond_t cond;
00449 
00450 public:
00451 
00452 /**
00453  * This class cannot be copied.  The copy constructor is deleted.
00454  */
00455   Cond(const Cond&) = delete;
00456 
00457 /**
00458  * This class cannot be copied.  The assignment operator is deleted.
00459  */
00460   Cond& operator=(const Cond&) = delete;
00461 
00462 /**
00463  * Unblock at least one thread waiting on this condition variable.
00464  * Can be called by any thread. It is not a cancellation point.  Does
00465  * not throw.
00466  * @return 0 if successful, otherwise the pthread error number.
00467  * @note With this library implementation, no pthread error should
00468  * arise so there is no need to check the return value.
00469  */
00470   int signal() {return pthread_cond_signal(&cond);}
00471 
00472 /**
00473  * Unblocks all threads waiting on this condition variable, which
00474  * acquire the mutex in an order determined by the scheduling policy.
00475  * Can be called by any thread. It is not a cancellation point.  Does
00476  * not throw.
00477  * @return 0 if successful, otherwise the pthread error number.  
00478  * @note With this library implementation, no pthread error should
00479  * arise so there is no need to check the return value.
00480  */
00481   int broadcast() {return pthread_cond_broadcast(&cond);}
00482 
00483 /**
00484  * Waits on this condition variable until unblocked or otherwise
00485  * awoken.  It must be called by the thread which owns the mutex.
00486  * Re-acquires the mutex when awoken.  It is a cancellation point.
00487  * This method is cancellation safe even if the stack does not unwind
00488  * on cancellation (but if the stack does not unwind some other way of
00489  * destroying this object on cancellation is required, such as by
00490  * having it allocated on freestore and deleted in a cancellation
00491  * clean-up handler).  This method does not throw.
00492  * @param mutex The locked mutex associated with the wait which is
00493  * re-acquired on being awoken.
00494  * @return 0 if successful, otherwise the pthread error number.
00495  * @note 1. pthread condition variables can, as a matter of design,
00496  * awake spontaneously (and Cond::signal() may awaken more than one
00497  * thread).  Therefore the relevant condition should be tested in a
00498  * while loop and not in an if block.
00499  * @note 2. With this library implementation, the only pthread error
00500  * numbers which could be returned are EINVAL (if the mutex argument
00501  * is not a valid mutex) or EPERM (if the thread calling this method
00502  * does not own the mutex).
00503  */
00504   int wait(Mutex& mutex) {return pthread_cond_wait(&cond, &mutex.pthr_mutex);}
00505 
00506 /**
00507  * Does the same as Cond::wait(Mutex&), except that as a convenience
00508  * it will take a Mutex::Lock object handling the Mutex object as an
00509  * alternative to passing the Mutex object itself.
00510  */
00511   int wait(Mutex::Lock& lock) {return wait(lock.mutex);}
00512 
00513 /**
00514  * Does the same as Cond::wait(Mutex&), except that as a convenience
00515  * it will take a Mutex::TrackLock object handling the Mutex object as
00516  * an alternative to passing the Mutex object itself.
00517  */
00518   int wait(Mutex::TrackLock& lock) {return wait(lock.mutex);}
00519 
00520 /**
00521  * Waits on this condition variable until unblocked or otherwise
00522  * awoken (in which case it re-acquires the mutex), or until the
00523  * timeout expires (in which case it re-acquires the mutex and returns
00524  * with ETIMEDOUT).  It must be called by the thread which owns the
00525  * mutex. Re-acquires the mutex when awoken or timing out.  It is a
00526  * cancellation point.  This method is cancellation safe even if the
00527  * stack does not unwind on cancellation (but if the stack does not
00528  * unwind some other way of destroying this object on cancellation is
00529  * required, such as by having it allocated on freestore and deleted
00530  * in a cancellation clean-up handler).  This method does not throw.
00531  * @param mutex The locked mutex associated with the wait which is
00532  * re-acquired on being awoken or timing out.
00533  * @param abs_time The time at which the wait will unblock if not
00534  * previously awoken.  A suitable value can be obtained by calling
00535  * the get_abs_time() function.
00536  * @return 0 if successful, otherwise ETIMEDOUT or other pthread error
00537  * number.
00538  * @note 1. With this library implementation, apart from ETIMEDOUT,
00539  * the only pthread error numbers which could be returned are EINVAL
00540  * (if the mutex argument is not a valid mutex or the abs_time
00541  * argument does not comprise a valid timespec struct) or EPERM (if
00542  * the thread calling this method does not own the mutex).
00543  * @note 2. pthread condition variables can, as a matter of design,
00544  * awake spontaneously (and Cond::signal() may awaken more than one
00545  * thread).  Therefore the relevant condition should be tested in a
00546  * while loop and not in an if block.
00547  * @note 3. If the system supports monotonic clocks (and this library
00548  * is not being cross-compiled onto a different architecture), then
00549  * condition variables will use a monotonic clock in
00550  * Cond::timed_wait() and Cond::get_abs_time().  This can be tested at
00551  * run time with Cond::have_monotonic_clock().
00552  */
00553   int timed_wait(Mutex& mutex, const timespec& abs_time) {
00554     return pthread_cond_timedwait(&cond, &mutex.pthr_mutex, &abs_time);
00555   }
00556 
00557 /**
00558  * Does the same as Cond::timed_wait(Mutex&, const timespec&), except
00559  * that as a convenience it will take a Mutex::Lock object handling
00560  * the Mutex object as an alternative to passing the Mutex object
00561  * itself.
00562  */
00563   int timed_wait(Mutex::Lock& lock,
00564                  const timespec& abs_time) {return timed_wait(lock.mutex, abs_time);}
00565 
00566 /**
00567  * Does the same as Cond::timed_wait(Mutex&, const timespec&), except
00568  * that as a convenience it will take a Mutex::TrackLock object
00569  * handling the Mutex object as an alternative to passing the Mutex
00570  * object itself.
00571  */
00572   int timed_wait(Mutex::TrackLock& lock,
00573                  const timespec& abs_time) {return timed_wait(lock.mutex, abs_time);}
00574 
00575 /**
00576  * This is a utility function that inserts into a timespec structure
00577  * the current time plus a given number of milliseconds ahead, which
00578  * can be applied to a call to Cond::timed_wait().  It does not throw.
00579  * It is thread-safe.
00580  * @param ts A timespec object into which the result of current time +
00581  * millisec will be placed.
00582  * @param millisec The number of milliseconds ahead of current time to
00583  * which the timespec object will be set.
00584  * @note If the system supports monotonic clocks (and this library is
00585  * not being cross-compiled onto a different architecture), then
00586  * condition variables will use a system monotonic clock in this
00587  * method and Cond::timed_wait().  This can be tested at run time with
00588  * Cond::have_monotonic_clock().
00589  */
00590   static void get_abs_time(timespec& ts, unsigned int millisec);
00591 
00592 /**
00593  * Indicates whether the library has been compiled with support for
00594  * monotonic clocks in Cond::timed_wait().  Most recent linux and BSD
00595  * distributions will support them, and this function would normally
00596  * return true unless the library has been cross-compiled from one
00597  * platform to a different platform.  This function can be tested at
00598  * program initialization, and if they are not supported a warning can
00599  * be given to the user about the deficiences of using the system
00600  * clock for timed events.  It does not throw.  It is thread safe.
00601  * @return true if the library has been compiled with support for
00602  * monotonic clocks in Cond::timed_wait(), otherwise false.
00603  */
00604   static bool have_monotonic_clock();
00605 
00606 /**
00607  * Initialises the pthread condition variable.  It is not a
00608  * cancellation point.
00609  * @exception Cgu::Thread::CondError Throws this exception if
00610  * initialization of the condition variable fails.  (It is often not
00611  * worth checking for CondError, as it means either memory is
00612  * exhausted or pthread has run out of other resources to create new
00613  * condition variables.)
00614  * @note If the system supports monotonic clocks (and this library is
00615  * not being cross-compiled onto a different architecture), then
00616  * condition variables will use a system monotonic clock in
00617  * Cond::timed_wait() and Cond::get_abs_time().  This can be tested at
00618  * run time by calling Cond::have_monotonic_clock().
00619  */
00620   Cond();
00621 
00622 /**
00623  * Destroys the pthread condition variable. It is not a cancellation
00624  * point.  The destructor does not throw.
00625  */
00626   ~Cond(void) {pthread_cond_destroy(&cond);}
00627 
00628 /* Only has effect if --with-glib-memory-slices-compat or
00629  * --with-glib-memory-slices-no-compat option picked */
00630   CGU_GLIB_MEMORY_SLICES_FUNCS
00631 };
00632 
00633 /**
00634  * @class RecMutex mutex.h c++-gtk-utils/mutex.h
00635  * @brief A wrapper class for pthread mutexes which provides a
00636  * recursive mutex.
00637  * @sa Thread::Thread Thread::RecMutex::Lock Thread::RecMutex::TrackLock Thread::Mutex
00638  *
00639  * This class can be used interchangeably with threads started with
00640  * GThread and by this library, as both glib and this library use
00641  * pthreads underneath on POSIX and other unix-like OSes.  It can also
00642  * be used interchangeably with those started by C++11 and with
00643  * std::recursive_mutex and similar objects, as in C++11 on unix-like
00644  * OSes these facilities will be built on top of pthreads (for which
00645  * purpose C++11 provides the std::native_handle_type type and
00646  * std::thread::native_handle() function), or if they are not, they
00647  * will use the same threading primitives provided by the kernel.
00648  *
00649  * There is no separate class for static mutexes.  That is not
00650  * necessary, as these RecMutex objects can be constructed statically
00651  * as well as dynamically and there is no need to call g_thread_init()
00652  * before they are constructed.  (If created as a static object in
00653  * global scope, it will not be possible to catch Thread::MutexError
00654  * or Thread::RecMutexError thrown by its constructor, but if a static
00655  * global mutex throws there is nothing that could be done anyway
00656  * except abort.)
00657  *
00658  * See the comments below on the test_support() method of this class,
00659  * about how the system's support for native recursive mutexes can be
00660  * tested at runtime and when a user program is compiled.
00661  */
00662 
00663 class RecMutex {
00664   pthread_mutex_t pthr_mutex;
00665   
00666 public:
00667   class Lock;
00668   class TrackLock;
00669 
00670 /**
00671  * This class cannot be copied.  The copy constructor is deleted.
00672  */
00673   RecMutex(const RecMutex&) = delete;
00674 
00675 /**
00676  * This class cannot be copied.  The assignment operator is deleted.
00677  */
00678   RecMutex& operator=(const RecMutex&) = delete;
00679 
00680 /**
00681  * Locks the mutex and acquires ownership.  Blocks if already locked
00682  * until it becomes free, unless the calling thread already holds the
00683  * lock, in which case it increments the lock count and returns
00684  * immediately.  It is not a cancellation point.  It does not throw.
00685  * It is thread safe.
00686  * @return 0 if successful, otherwise the pthread mutex error number.
00687  * @note With this library implementation, the only pthread error
00688  * number which could be returned by this method is EAGAIN, which it
00689  * would do if the maximum recursive lock count for this mutex has
00690  * been reached.  Usually this number is at or around INT_MAX and
00691  * hence the return value is usually not worth checking for.
00692  */
00693   int lock() {return pthread_mutex_lock(&pthr_mutex);}
00694 
00695 /**
00696  * Tries to lock the mutex and acquire ownership, but returns
00697  * immediately if it is already locked with value EBUSY unless the
00698  * calling thread already holds the lock, in which case it returns
00699  * normally and increments the lock count.  It is not a cancellation
00700  * point.  It does not throw.  It is thread safe.
00701  * @return 0 if successful, otherwise EBUSY or other pthread mutex
00702  * error number.
00703  * @note With this library implementation, apart from EBUSY, the only
00704  * other pthread error number which could be returned by this method
00705  * is EAGAIN, which it would do if the maximum recursive lock count
00706  * for this mutex has been reached.  Usually this number is at or
00707  * around INT_MAX and hence an EAGAIN error return value is usually
00708  * not worth checking for except during debugging.
00709  */
00710   int trylock() {return pthread_mutex_trylock(&pthr_mutex);}
00711 
00712 /**
00713  * Unlocks a locked mutex owned by the calling thread and either
00714  * relinquishes ownership (if the mutex has not been recursively
00715  * locked) or decrements the lock count (if it has).  It is not a
00716  * cancellation point.  It does not throw.  It must be called by the
00717  * thread which owns the mutex.
00718  * @return 0 if successful, otherwise the pthread mutex error number.  
00719  * @note With this library implementation, the only pthread error
00720  * number which could be returned by this method is EPERM because the
00721  * calling thread does not own the mutex (however POSIX does not
00722  * require that return value in that case and hence the return value
00723  * is usually not worth checking for except during debugging).
00724  */
00725   int unlock() {return pthread_mutex_unlock(&pthr_mutex);}
00726 
00727 /**
00728  * Indicates whether the system supports recursive mutexes.  This
00729  * method does not throw.  It is thread safe.
00730  * @return 0 if the system supports recursive mutexes, -1 if it does
00731  * not support recursive mutexes and 1 if pthread has run out of
00732  * sufficient resources to test this at run time (in which case any
00733  * attempt to create mutexes or start threads is likely to fail).
00734  * Practically all recent linux and BSD distributions will support
00735  * them, and this function would normally return 0.  If it does not,
00736  * it is still possible to use GStaticRecMutex objects (for which
00737  * purpose see Cgu::Thread::GrecmutexLock).
00738  *
00739  * @note The header file <c++-gtk-utils/cgu_config.h> defines the
00740  * symbol CGU_HAVE_RECURSIVE_MUTEX if native recursive mutexes were
00741  * found to be supported when this library was compiled.  Programs
00742  * using this library can therefore test for that symbol with the
00743  * pre-processor for conditional compilation purposes (so that the
00744  * program can, for example, be compiled to use GStaticRecMutex if
00745  * that symbol is not defined).  However, if the library was
00746  * cross-compiled from one architecture to another, that symbol may
00747  * not be defined even though the target architecture does, in fact,
00748  * support them at program runtime.  In other words, if
00749  * CGU_HAVE_RECURSIVE_MUTEX is defined then this method will always
00750  * return 0; but in the event of cross-compilation of the library this
00751  * method (which provides a separate runtime test) might return 0,
00752  * correctly showing support, even when CGU_HAVE_RECURSIVE_MUTEX is
00753  * not defined.
00754  */
00755   static int test_support();
00756 
00757 /**
00758  * Initialises the pthread mutex.  It is not a cancellation point.
00759  * @exception Cgu::Thread::RecMutexError Throws this exception if the
00760  * system does not support recursive mutexes.  (If this has been
00761  * checked beforehand, say by calling test_support(), there should be
00762  * no need to check for this exception.)
00763  * @exception Cgu::Thread::MutexError Throws this exception if
00764  * initialization of the mutex fails, except because the system does
00765  * not support recursive mutexes.  (It is often not worth checking for
00766  * MutexError, as it means either memory is exhausted or pthread has
00767  * run out of other resources to create new mutexes.)
00768  */
00769   RecMutex();
00770 
00771 /**
00772  *  Destroys the pthread mutex.  It is not a cancellation point.  It
00773  *  does not throw.
00774  */
00775   ~RecMutex() {pthread_mutex_destroy(&pthr_mutex);}
00776 
00777 /* Only has effect if --with-glib-memory-slices-compat or
00778  * --with-glib-memory-slices-no-compat option picked */
00779   CGU_GLIB_MEMORY_SLICES_FUNCS
00780 };
00781 
00782 /**
00783  * @class RecMutex::Lock mutex.h c++-gtk-utils/mutex.h
00784  * @brief A scoped locking class for exception safe RecMutex locking.
00785  * @sa Thread::RecMutex Thread::RecMutex::TrackLock Thread::Thread
00786  */
00787 
00788 class RecMutex::Lock {
00789   RecMutex& mutex;
00790 
00791 public:
00792 /**
00793  * This class cannot be copied.  The copy constructor is deleted.
00794  */
00795   Lock(const RecMutex::Lock&) = delete;
00796 
00797 /**
00798  * This class cannot be copied.  The assignment operator is deleted.
00799  */
00800   RecMutex::Lock& operator=(const RecMutex::Lock&) = delete;
00801 
00802 /**
00803  * This calls RecMutex::lock(), and so locks the mutex and reacquires
00804  * ownership.  It blocks if the mutex is already locked until the
00805  * mutex becomes free, unless the calling thread already holds the
00806  * lock, in which case it increments the lock count and returns
00807  * immediately.  This method should normally only be called if a
00808  * previous call has been made to RecMutex::Lock::unlock() (that is,
00809  * where the thread owning the RecMutex::Lock object has temporarily
00810  * allowed another thread to take the mutex concerned if it is not
00811  * recursively locked).  It is not a cancellation point.  It does not
00812  * throw.
00813  * @return 0 if successful, otherwise the pthread mutex error number.
00814  * @note With this library implementation, the only pthread error
00815  * number which could be returned by this method is EAGAIN, which it
00816  * would do if the maximum recursive lock count for the particular
00817  * mutex in question has been reached.  Usually this number is at or
00818  * around INT_MAX and hence the return value is usually not worth
00819  * checking for except during debugging.
00820  * @sa RecMutex::TrackLock.
00821  */
00822   int lock() {return mutex.lock();}
00823 
00824 /**
00825  * This calls RecMutex::trylock(), and so tries to lock the mutex and
00826  * reacquire ownership, but returns immediately if it is already
00827  * locked with value EBUSY unless the calling thread already holds the
00828  * lock, in which case it returns normally and increments the lock
00829  * count.  This method should normally only be called if a previous
00830  * call has been made to RecMutex::Lock::unlock() (that is, where the
00831  * thread owning the RecMutex::Lock object has temporarily allowed
00832  * another thread to take the mutex concerned if it is not recursively
00833  * locked).  It is not a cancellation point.  It does not throw.
00834  * @return 0 if successful, otherwise EBUSY or other pthread mutex
00835  * error number.
00836  * @note With this library implementation, apart from EBUSY, the only
00837  * other pthread error number which could be returned by this method
00838  * is EAGAIN, which it would do if the maximum recursive lock count
00839  * for the particular mutex in question has been reached.  Usually
00840  * this number is at or around INT_MAX and hence an EAGAIN error
00841  * return value is usually not worth checking for except during
00842  * debugging.
00843  * @sa RecMutex::TrackLock.
00844  */
00845  int trylock() {return mutex.trylock();}
00846 
00847 /**
00848  * This calls RecMutex::unlock() and so unlocks a locked mutex owned
00849  * by the calling thread, so temporarily allowing another thread to
00850  * take the mutex if the mutex has not been recursively locked, or if
00851  * it has been recursively locked decrements the lock count, so
00852  * temporarily relinquishing ownership.  This method should normally
00853  * only be called if it is to be followed by a call to
00854  * RecMutex::Lock::lock() or a successful call to
00855  * RecMutex::Lock::trylock() before the RecMutex::Lock object
00856  * concerned goes out of scope (otherwise RecMutex::Lock's destructor
00857  * will attempt to decrement the lock count of a mutex which already
00858  * has a lock count of 0 or which another thread has by then taken
00859  * ownership or leave the lock count in an unbalanced condition -
00860  * RecMutex::Lock objects do not maintain state).  See
00861  * RecMutex::TrackLock::unlock() for a safe version of this method.
00862  * It is not a cancellation point.  It does not throw.
00863  * @return 0 if successful, otherwise the pthread mutex error number.  
00864  * @note With this library implementation, the only pthread error
00865  * number which could be returned by this method is EPERM because the
00866  * calling thread does not own the particular mutex in question
00867  * (however POSIX does not require that return value in that case and
00868  * hence the return value is usually not worth checking for except
00869  * during debugging).
00870  * @sa RecMutex::TrackLock.
00871  */
00872  int unlock() {return mutex.unlock();}
00873 
00874 /**
00875  * This constructor locks the mutex passed to it.  See
00876  * RecMutex::lock() for a description of the outcomes.  It is not a
00877  * cancellation point.
00878  * @param mutex_ The mutex to be locked.
00879  * @exception Cgu::Thread::RecMutexError Throws this exception if
00880  * initialization of the mutex fails because the maximum recursive
00881  * lock count for the particular mutex in question has been reached.
00882  * Usually this number is at or around INT_MAX so it is not usually
00883  * useful to check for it except during debugging.
00884  */
00885   Lock(RecMutex& mutex_): mutex(mutex_) {if (mutex.lock()) throw RecMutexError();}
00886 
00887 /**
00888  * This constructor takes an already locked mutex (say as a result of
00889  * RecMutex::trylock()), and takes ownership of it.  It is not a
00890  * cancellation point.  It does not throw.
00891  * @param mutex_ The mutex to be managed by this object.
00892  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
00893  */
00894   Lock(RecMutex& mutex_, Locked tag): mutex(mutex_) {}
00895 
00896 /**
00897  * This class requires initialisation with a RecMutex.  The default
00898  * constructor is deleted.
00899  */
00900   Lock() = delete;
00901 
00902 /**
00903  * The destructor unlocks the owned mutex.  See RecMutex::unlock() for
00904  * a description of the outcomes.  It is not a cancellation point.  It
00905  * does not throw.
00906  */
00907   ~Lock() {mutex.unlock();}
00908 
00909 /* Only has effect if --with-glib-memory-slices-compat or
00910  * --with-glib-memory-slices-no-compat option picked */
00911   CGU_GLIB_MEMORY_SLICES_FUNCS
00912 };
00913 
00914 /**
00915  * @class RecMutex::TrackLock mutex.h c++-gtk-utils/mutex.h
00916  * @brief A scoped locking class for exception safe RecMutex locking
00917  * which tracks the status of its mutex.
00918  * @sa Thread::RecMutex Thread::RecMutex::Lock Thread::Thread
00919  *
00920  * This class is similar to a RecMutex::Lock object, except that it
00921  * tracks whether the mutex it manages is locked by the thread
00922  * creating the RecMutex::TrackLock object with respect to the
00923  * particular locking operation to be governed by the object (provided
00924  * that, while the RecMutex::TrackLock object exists, the thread
00925  * creating it only accesses the mutex with respect that particular
00926  * operation through that object).  This enables
00927  * RecMutex::TrackLock::unlock() to be used without it being followed
00928  * later by a call to RecMutex::TrackLock::lock() or a successful call
00929  * to RecMutex::TrackLock::trylock(), and also permits locking to be
00930  * deferred until after construction of the lock object.  Note that
00931  * only one thread may call the methods of any one RecMutex::TrackLock
00932  * object, including causing its destructor to be invoked.
00933  */
00934 
00935 class RecMutex::TrackLock {
00936   RecMutex& mutex;
00937   bool owner;
00938 
00939 public:
00940 
00941 /**
00942  * This class cannot be copied.  The copy constructor is deleted.
00943  */
00944   TrackLock(const RecMutex::TrackLock&) = delete;
00945 
00946 /**
00947  * This class cannot be copied.  The assignment operator is deleted.
00948  */
00949   RecMutex::TrackLock& operator=(const RecMutex::TrackLock&) = delete;
00950 
00951 /**
00952  * This calls RecMutex::lock(), and so locks the mutex and acquires
00953  * ownership.  It blocks if the mutex is already locked until the
00954  * mutex becomes free, unless the calling thread already holds the
00955  * lock, in which case it increments the lock count and returns
00956  * immediately.  This method should normally only be called if a
00957  * previous call has been made to RecMutex::TrackLock::unlock() or
00958  * this RecMutex::TrackLock object has been constructed with the
00959  * Thread::defer enum tag.  It is not a cancellation point.  It does
00960  * not throw.
00961  * @return 0 if successful, otherwise the pthread mutex error number.
00962  * @note With this library implementation, the only pthread error
00963  * number which could be returned by this method is EAGAIN, which it
00964  * would do if the maximum recursive lock count for the particular
00965  * mutex in question has been reached.  Usually this number is at or
00966  * around INT_MAX and hence the return value is usually not worth
00967  * checking for except during debugging.
00968  */
00969   int lock() {int ret = mutex.lock(); if (!owner) owner = !ret; return ret;}
00970 
00971 /**
00972  * This calls RecMutex::trylock(), and so tries to lock the mutex and
00973  * acquire ownership, but returns immediately if it is already locked
00974  * with value EBUSY unless the calling thread already holds the lock,
00975  * in which case it returns normally and increments the lock count.
00976  * This method should normally only be called if a previous call has
00977  * been made to RecMutex::TrackLock::unlock() or this
00978  * RecMutex::TrackLock object has been constructed with the
00979  * Thread::defer enum tag.  It is not a cancellation point.  It does
00980  * not throw.
00981  * @return 0 if successful, otherwise EBUSY or other pthread mutex
00982  * error number.
00983  * @note With this library implementation, apart from EBUSY, the only
00984  * other pthread error number which could be returned by this method
00985  * is EAGAIN, which it would do if the maximum recursive lock count
00986  * for the particular mutex in question has been reached.  Usually
00987  * this number is at or around INT_MAX and hence an EAGAIN error
00988  * return value is usually not worth checking for except during
00989  * debugging.
00990  */
00991   int trylock() {int ret = mutex.trylock(); if (!owner) owner = !ret; return ret;}
00992 
00993 /**
00994  * This calls RecMutex::unlock(), and so unlocks a locked mutex owned
00995  * by the calling thread, or decrements the lock count (if it has been
00996  * recursively locked).  It will cause is_owner() to return false
00997  * unless a subsequent call is made to lock() or a subsequent
00998  * successful call is made to trylock().  It is not a cancellation
00999  * point.  It does not throw.
01000  * @return 0 if successful, otherwise the pthread mutex error number.
01001  * @note With this library implementation, the only pthread error
01002  * number which could be returned by this method is EPERM because the
01003  * calling thread does not own the particular mutex in question
01004  * (however POSIX does not require that return value in that case and
01005  * hence the return value is usually not worth checking for except
01006  * during debugging).
01007  */
01008   int unlock() {int ret = mutex.unlock(); if (owner) owner = ret; return ret;}
01009 
01010 /**
01011  * Indicates whether the mutex managed by this Mutex::TrackLock object
01012  * is locked by it (whether originally or recursively) and so owned by
01013  * it.
01014  * @return true if the mutex is owned by this object, otherwise false.
01015  */
01016   bool is_owner() const {return owner;}
01017 
01018 /**
01019  * This constructor locks the mutex passed to it.  See
01020  * RecMutex::lock() for a description of the outcomes.  It is not a
01021  * cancellation point.  It does not throw.
01022  * @param mutex_ The mutex to be locked.
01023  * @exception Cgu::Thread::RecMutexError Throws this exception if
01024  * initialization of the mutex fails because the maximum recursive
01025  * lock count for the particular mutex in question has been reached.
01026  * Usually this number is at or around INT_MAX so it is not usually
01027  * useful to check for it except during debugging.
01028  */
01029   TrackLock(RecMutex& mutex_): mutex(mutex_), owner(true) {if (mutex.lock()) throw RecMutexError();}
01030 
01031 /**
01032  * This constructor takes an already locked mutex (say as a result of
01033  * RecMutex::trylock()), and takes ownership of it.  It is not a
01034  * cancellation point.  It does not throw.
01035  * @param mutex_ The mutex to be managed by this object.
01036  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
01037  */
01038   TrackLock(RecMutex& mutex_, Locked tag): mutex(mutex_), owner(true) {}
01039 
01040 /**
01041  * This constructor defers locking of the mutex (and so taking
01042  * ownership of it) until an explicit call to lock() or trylock() is
01043  * made.  It is not a cancellation point.  It does not throw.
01044  * @param mutex_ The mutex to be managed by this object.
01045  * @param tag Pass the Cgu::Thread::defer enum tag to this parameter.
01046  */
01047   TrackLock(RecMutex& mutex_, DeferLock tag): mutex(mutex_), owner(false) {}
01048 
01049 /**
01050  * This class requires initialisation with a RecMutex.  The default
01051  * constructor is deleted.
01052  */
01053   TrackLock() = delete;
01054 
01055 /**
01056  * The destructor unlocks the managed mutex if it is owned by this
01057  * RecMutex::TrackLock object.  See RecMutex::unlock() for a
01058  * description of the outcomes if it is so owned.  It is not a
01059  * cancellation point.  It does not throw.
01060  */
01061   ~TrackLock() {if (owner) mutex.unlock();}
01062 
01063 /* Only has effect if --with-glib-memory-slices-compat or
01064  * --with-glib-memory-slices-no-compat option picked */
01065   CGU_GLIB_MEMORY_SLICES_FUNCS
01066 };
01067 
01068 /**
01069  * @class GrecmutexLock mutex.h c++-gtk-utils/mutex.h
01070  * @brief A scoped locking class for exception safe locking of
01071  * GStaticRecMutex objects.
01072  * @details This class is mainly intended for use where the native
01073  * pthreads implementation does not support recursive mutexes so
01074  * Cgu::Thread::RecMutex and Cgu::Thread::RecMutex::Lock cannot be
01075  * used.
01076  */
01077 class GrecmutexLock {
01078   GStaticRecMutex& mutex;
01079 public:
01080 
01081 /**
01082  * This class cannot be copied.  The copy constructor is deleted.
01083  */
01084   GrecmutexLock(const GrecmutexLock&) = delete;
01085 
01086 /**
01087  * This class cannot be copied.  The assignment operator is deleted.
01088  */
01089   GrecmutexLock& operator=(const GrecmutexLock&) = delete;
01090 
01091 /**
01092  * This method provides access to the GStaticRecMutex object locked by
01093  * this GrecmutexLock object.  It does not throw.  It is thread safe.
01094  * @return A pointer to the GStaticRecMutex object.
01095  */
01096   GStaticRecMutex* get() const {return &mutex;}
01097 /**
01098  * This constructor locks the mutex and acquires ownership, and blocks
01099  * if it is already locked until it becomes free, unless the
01100  * constructing thread already holds the lock, in which case it
01101  * increments the lock count and returns immediately.  It is not a
01102  * cancellation point.  It does not throw.
01103  * @param mutex_ The mutex to be locked.
01104  */
01105   GrecmutexLock(GStaticRecMutex& mutex_): mutex(mutex_) {g_static_rec_mutex_lock(&mutex);}
01106 
01107 /**
01108  * This constructor takes an already locked mutex (say as a result of
01109  * g_static_rec_mutex_trylock()), and takes ownership of it.  It is not a
01110  * cancellation point.  It does not throw.
01111  * @param mutex_ The mutex to be managed by this object.
01112  * @param tag Pass the Cgu::Thread::locked enum tag to this parameter.
01113  */
01114   GrecmutexLock(GStaticRecMutex& mutex_, Locked tag): mutex(mutex_) {}
01115 
01116 /**
01117  * This class requires initialisation with a GStaticRecMutex.  The
01118  * default constructor is deleted.
01119  */
01120   GrecmutexLock() = delete;
01121 
01122 /**
01123  * The destructor unlocks the owned mutex, and either relinquishes
01124  * ownership (if the mutex has not been recursively locked) or
01125  * decrements the lock count (if it has).  It is not a cancellation
01126  * point.  It does not throw.
01127  */
01128   ~GrecmutexLock() {g_static_rec_mutex_unlock(&mutex);}
01129 
01130 /* Only has effect if --with-glib-memory-slices-compat or
01131  * --with-glib-memory-slices-no-compat option picked */
01132   CGU_GLIB_MEMORY_SLICES_FUNCS
01133 };
01134 
01135 } // namespace Thread
01136 
01137 } // namespace Cgu
01138 
01139 #endif