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