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