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. 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