c++-gtk-utils

mutex.h

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