c++-gtk-utils
|
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