00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef cxxtools_Mutex_h
00029 #define cxxtools_Mutex_h
00030
00031 #include <cxxtools/api.h>
00032 #include <cxxtools/atomicity.h>
00033 #include <cxxtools/noncopyable.h>
00034 #include <cxxtools/thread.h>
00035
00036 namespace cxxtools {
00037
00045 class CXXTOOLS_API Mutex : private NonCopyable
00046 {
00047 private:
00048 class MutexImpl* _impl;
00049
00050 public:
00052 Mutex();
00053
00059 ~Mutex();
00060
00068 void lock();
00069
00070 bool tryLock();
00071
00073 void unlock();
00074
00080 bool unlockNoThrow();
00081
00083 MutexImpl& impl()
00084 { return *_impl; }
00085 };
00086
00118 class MutexLock : private NonCopyable
00119 {
00120 public:
00128 MutexLock(Mutex& m, bool doLock = true, bool isLocked = false)
00129 : _mutex(m)
00130 , _isLocked(isLocked)
00131 {
00132 if(doLock)
00133 this->lock();
00134 }
00135
00137 ~MutexLock()
00138 {
00139 if(_isLocked)
00140 _mutex.unlockNoThrow();
00141 }
00142
00143 void lock()
00144 {
00145 if(!_isLocked)
00146 {
00147 _mutex.lock();
00148 _isLocked = true;
00149 }
00150 }
00151
00153 void unlock()
00154 {
00155 if(_isLocked)
00156 {
00157 _mutex.unlock();
00158 _isLocked = false;
00159 }
00160 }
00161
00163 Mutex& mutex()
00164 { return _mutex; }
00165
00167 const Mutex& mutex() const
00168 { return _mutex; }
00169
00170 private:
00171 Mutex& _mutex;
00172 bool _isLocked;
00173 };
00174
00177 class CXXTOOLS_API RecursiveMutex : private NonCopyable
00178 {
00179 private:
00180 class MutexImpl* _impl;
00181
00182 public:
00183 RecursiveMutex();
00184
00185 ~RecursiveMutex();
00186
00187 void lock();
00188
00189 bool tryLock();
00190
00197 void unlock();
00198
00199 bool unlockNoThrow();
00200 };
00201
00204 class RecursiveLock : private NonCopyable
00205 {
00206 public:
00214 RecursiveLock(RecursiveMutex& m, bool doLock = true, bool isLocked = false)
00215 : _mutex(m)
00216 , _isLocked(isLocked)
00217 {
00218 if(doLock)
00219 this->lock();
00220 }
00221
00223 ~RecursiveLock()
00224 {
00225 if(_isLocked)
00226 _mutex.unlockNoThrow();
00227 }
00228
00229 void lock()
00230 {
00231 if(!_isLocked)
00232 {
00233 _mutex.lock();
00234 _isLocked = true;
00235 }
00236 }
00237
00239 void unlock()
00240 {
00241 if(_isLocked)
00242 {
00243 _mutex.unlock();
00244 _isLocked = false;
00245 }
00246 }
00247
00249 RecursiveMutex& mutex()
00250 { return _mutex; }
00251
00253 const RecursiveMutex& mutex() const
00254 { return _mutex; }
00255
00256 private:
00257 RecursiveMutex& _mutex;
00258 bool _isLocked;
00259 };
00260
00266 class CXXTOOLS_API ReadWriteMutex : private NonCopyable
00267 {
00268 public:
00270 ReadWriteMutex();
00271
00273 ~ReadWriteMutex();
00274
00275 void readLock();
00281 bool tryReadLock();
00282
00289 void writeLock();
00290
00297 bool tryWriteLock();
00298
00300 void unlock();
00301
00302 bool unlockNoThrow();
00303
00304 private:
00306 class ReadWriteMutexImpl* _impl;
00307 };
00308
00309
00310 class ReadLock : private NonCopyable
00311 {
00312 public:
00313 ReadLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
00314 : _mutex(m)
00315 , _locked(isLocked)
00316 {
00317 if(doLock)
00318 this->lock();
00319 }
00320
00321 ~ReadLock()
00322 {
00323 if(_locked)
00324 _mutex.unlockNoThrow();
00325 }
00326
00327 void lock()
00328 {
00329 if( ! _locked )
00330 {
00331 _mutex.readLock();
00332 _locked = true;
00333 }
00334 }
00335
00336 void unlock()
00337 {
00338 if( _locked)
00339 {
00340 _mutex.unlock();
00341 _locked = false;
00342 }
00343 }
00344
00345 ReadWriteMutex& mutex()
00346 { return _mutex; }
00347
00348 private:
00349 ReadWriteMutex& _mutex;
00350 bool _locked;
00351 };
00352
00353
00354 class WriteLock : private NonCopyable
00355 {
00356 public:
00357 WriteLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
00358 : _mutex(m)
00359 , _locked(isLocked)
00360 {
00361 if(doLock)
00362 this->lock();
00363 }
00364
00365 ~WriteLock()
00366 {
00367 if(_locked)
00368 _mutex.unlockNoThrow();
00369 }
00370
00371 void lock()
00372 {
00373 if( ! _locked )
00374 {
00375 _mutex.writeLock();
00376 _locked = true;
00377 }
00378 }
00379
00380 void unlock()
00381 {
00382 if( _locked)
00383 {
00384 _mutex.unlock();
00385 _locked = false;
00386 }
00387 }
00388
00389 ReadWriteMutex& mutex()
00390 { return _mutex; }
00391
00392 private:
00393 ReadWriteMutex& _mutex;
00394 bool _locked;
00395 };
00396
00397
00411 class SpinMutex : private NonCopyable
00412 {
00413 public:
00415 SpinMutex()
00416 : _count(0)
00417 {}
00418
00420 ~SpinMutex()
00421 {}
00422
00423
00432 inline void lock()
00433 {
00434
00435 while( atomicCompareExchange(_count, 1, 0) )
00436 {
00437 Thread::yield();
00438 }
00439 }
00440
00441 bool tryLock()
00442 {
00443 return ! atomicCompareExchange(_count, 1, 0);
00444 }
00445
00447 void unlock()
00448 {
00449
00450 atomicExchange(_count, 0);
00451 }
00452
00454 bool testIsLocked() const
00455 { return _count != 0; }
00456
00457 private:
00458 volatile cxxtools::atomic_t _count;
00459 };
00460
00461
00462 class SpinLock : private NonCopyable
00463 {
00464 public:
00465 SpinLock(SpinMutex& m, bool doLock = true, bool isLocked = false)
00466 : _mutex(m)
00467 , _locked(isLocked)
00468 {
00469 if(doLock)
00470 this->lock();
00471 }
00472
00473 ~SpinLock()
00474 {
00475 if(_locked)
00476 this->unlock();
00477 }
00478
00479 void lock()
00480 {
00481 if( ! _locked )
00482 {
00483 _mutex.lock();
00484 _locked = true;
00485 }
00486 }
00487
00488 void unlock()
00489 {
00490 if( _locked)
00491 {
00492 _mutex.unlock();
00493 _locked = false;
00494 }
00495 }
00496
00497 private:
00498 SpinMutex& _mutex;
00499 bool _locked;
00500 };
00501
00502 }
00503
00504 #endif