Mutex.h
1 /*
2  * Copyright (C) 2005-2008 by Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef Pt_System_Mutex_h
30 #define Pt_System_Mutex_h
31 
32 #include <Pt/Atomicity.h>
33 #include <Pt/NonCopyable.h>
34 #include <Pt/System/Api.h>
35 #include <Pt/System/Thread.h>
36 
37 namespace Pt {
38 
39 namespace System {
40 
48 class PT_SYSTEM_API Mutex : private NonCopyable
49 {
50  private:
51  class MutexImpl* _impl;
52 
53  public:
55  Mutex();
56 
62  ~Mutex();
63 
71  void lock();
72 
78  bool tryLock();
79 
81  void unlock();
82 
88  bool unlockNoThrow();
89 
91  MutexImpl& impl()
92  { return *_impl; }
93 };
94 
126 class MutexLock : private NonCopyable
127 {
128  public:
136  MutexLock(Mutex& m, bool doLock = true, bool isLocked = false)
137  : _mutex(m)
138  , _isLocked(isLocked)
139  {
140  if(doLock)
141  this->lock();
142  }
143 
146  {
147  if(_isLocked)
148  _mutex.unlockNoThrow();
149  }
150 
153  void lock()
154  {
155  if(!_isLocked)
156  {
157  _mutex.lock();
158  _isLocked = true;
159  }
160  }
161 
163  void unlock()
164  {
165  if(_isLocked)
166  {
167  _mutex.unlock();
168  _isLocked = false;
169  }
170  }
171 
174  { return _mutex; }
175 
177  const Mutex& mutex() const
178  { return _mutex; }
179 
180  private:
181  Mutex& _mutex;
182  bool _isLocked;
183 };
184 
187 class PT_SYSTEM_API RecursiveMutex : private NonCopyable
188 {
189  private:
190  class MutexImpl* _impl;
191 
192  public:
194  RecursiveMutex();
195 
197  ~RecursiveMutex();
198 
200  void lock();
201 
203  bool tryLock();
204 
211  void unlock();
212 
214  bool unlockNoThrow();
215 };
216 
219 class RecursiveLock : private NonCopyable
220 {
221  public:
229  RecursiveLock(RecursiveMutex& m, bool doLock = true, bool isLocked = false)
230  : _mutex(m)
231  , _isLocked(isLocked)
232  {
233  if(doLock)
234  this->lock();
235  }
236 
239  {
240  if(_isLocked)
241  _mutex.unlockNoThrow();
242  }
243 
245  void lock()
246  {
247  if(!_isLocked)
248  {
249  _mutex.lock();
250  _isLocked = true;
251  }
252  }
253 
255  void unlock()
256  {
257  if(_isLocked)
258  {
259  _mutex.unlock();
260  _isLocked = false;
261  }
262  }
263 
266  { return _mutex; }
267 
269  const RecursiveMutex& mutex() const
270  { return _mutex; }
271 
272  private:
273  RecursiveMutex& _mutex;
274  bool _isLocked;
275 };
276 
282 class PT_SYSTEM_API ReadWriteMutex : private NonCopyable
283 {
284  public:
286  ReadWriteMutex();
287 
289  ~ReadWriteMutex();
290 
296  void readLock();
297 
304  bool tryReadLock();
305 
312  void writeLock();
313 
320  bool tryWriteLock();
321 
323  void unlock();
324 
326  bool unlockNoThrow();
327 
328  private:
330  class ReadWriteMutexImpl* _impl;
331 };
332 
335 class ReadLock : private NonCopyable
336 {
337  public:
345  ReadLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
346  : _mutex(m)
347  , _locked(isLocked)
348  {
349  if(doLock)
350  this->lock();
351  }
352 
355  {
356  if(_locked)
357  _mutex.unlockNoThrow();
358  }
359 
361  void lock()
362  {
363  if( ! _locked )
364  {
365  _mutex.readLock();
366  _locked = true;
367  }
368  }
369 
371  void unlock()
372  {
373  if( _locked)
374  {
375  _mutex.unlock();
376  _locked = false;
377  }
378  }
379 
382  { return _mutex; }
383 
384  private:
385  ReadWriteMutex& _mutex;
386  bool _locked;
387 };
388 
391 class WriteLock : private NonCopyable
392 {
393  public:
401  WriteLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
402  : _mutex(m)
403  , _locked(isLocked)
404  {
405  if(doLock)
406  this->lock();
407  }
408 
411  {
412  if(_locked)
413  _mutex.unlockNoThrow();
414  }
415 
417  void lock()
418  {
419  if( ! _locked )
420  {
421  _mutex.writeLock();
422  _locked = true;
423  }
424  }
425 
427  void unlock()
428  {
429  if( _locked)
430  {
431  _mutex.unlock();
432  _locked = false;
433  }
434  }
435 
438  { return _mutex; }
439 
440  private:
441  ReadWriteMutex& _mutex;
442  bool _locked;
443 };
444 
445 
459 class SpinMutex : private NonCopyable
460 {
461  public:
464  : _count(0)
465  {}
466 
469  {}
470 
479  inline void lock()
480  {
481  // busy loop until unlock
482  while( atomicCompareExchange(_count, 1, 0) )
483  {
484  Thread::yield();
485  }
486  }
487 
493  bool tryLock()
494  {
495  return ! atomicCompareExchange(_count, 1, 0);
496  }
497 
499  void unlock()
500  {
501  // set unlocked
502  atomicExchange(_count, 0);
503  }
504 
506  bool testIsLocked() const
507  { return atomicGet(const_cast<volatile Pt::atomic_t&>(_count)) != 0; }
508 
509  private:
510  volatile Pt::atomic_t _count;
511 };
512 
515 class SpinLock : private NonCopyable
516 {
517  public:
525  SpinLock(SpinMutex& m, bool doLock = true, bool isLocked = false)
526  : _mutex(m)
527  , _locked(isLocked)
528  {
529  if(doLock)
530  this->lock();
531  }
532 
535  {
536  if(_locked)
537  this->unlock();
538  }
539 
541  void lock()
542  {
543  if( ! _locked )
544  {
545  _mutex.lock();
546  _locked = true;
547  }
548  }
549 
551  void unlock()
552  {
553  if( _locked)
554  {
555  _mutex.unlock();
556  _locked = false;
557  }
558  }
559 
560  private:
561  SpinMutex& _mutex;
562  bool _locked;
563 };
564 
565 } // namespace System
566 
567 } // namespace Pt
568 
569 #endif // Pt_System_Mutex_h
Lock object for spin mutexes.
Definition: Mutex.h:515
void lock()
Locks the mutex.
Definition: Mutex.h:361
void lock()
Lock the mutex.
Definition: Mutex.h:153
Atomic integers to be used with atomicity functions.
Definition: Atomicity.h:50
~ReadLock()
Unlocks the mutex unless unlock() was called.
Definition: Mutex.h:354
void lock()
Lock the mutex.
Protects derived classes from being copied.
Definition: NonCopyable.h:54
Recursive mutual exclusion device.
Definition: Mutex.h:187
SpinMutex()
Default Constructor.
Definition: Mutex.h:463
void unlock()
Unlocks the mutex.
Definition: Mutex.h:499
ReadLock(ReadWriteMutex &m, bool doLock=true, bool isLocked=false)
Construct to guard a ReadWriteMutex.
Definition: Mutex.h:345
void lock()
Locks the mutex.
Definition: Mutex.h:541
Synchronisation device similar to a POSIX rwlock.
Definition: Mutex.h:282
void lock()
Locks the mutex.
~SpinMutex()
Destructor.
Definition: Mutex.h:468
void writeLock()
Acquires a write lock.
void unlock()
Unlocks the mutex.
Definition: Mutex.h:255
void unlock()
Unlocks the mutex.
Definition: Mutex.h:371
static void yield()
Yield CPU time.
void unlock()
Unlocks the mutex.
void unlock()
Releases the read or write lock.
void lock()
Locks the mutex.
Definition: Mutex.h:417
bool tryLock()
Tries to acquire a lock.
Definition: Mutex.h:493
ReadWriteMutex & mutex()
Returns the guarded the mutex object.
Definition: Mutex.h:381
void unlock()
Unlock so that the destructor does not unlock.
Definition: Mutex.h:163
void unlock()
Unlocks the mutex.
Definition: Mutex.h:427
Mutual exclusion device.
Definition: Mutex.h:48
~WriteLock()
Unlocks the mutex unless unlock() was called.
Definition: Mutex.h:410
bool unlockNoThrow()
Unlocks the mutex.
~MutexLock()
Unlocks the mutex unless unlock() was called.
Definition: Mutex.h:145
Spinmutex class.
Definition: Mutex.h:459
void unlock()
Unlocks the mutex.
Definition: Mutex.h:551
Lock class for recursive mutexes.
Definition: Mutex.h:219
Reader lock object for read-write mutexes.
Definition: Mutex.h:335
~RecursiveLock()
Unlocks the mutex unless unlock() was called.
Definition: Mutex.h:238
RecursiveMutex & mutex()
Returns the guarded the mutex object.
Definition: Mutex.h:265
SpinLock(SpinMutex &m, bool doLock=true, bool isLocked=false)
Construct to guard a SpinMutex.
Definition: Mutex.h:525
Mutex & mutex()
Returns the guarded the mutex object.
Definition: Mutex.h:173
MutexLock(Mutex &m, bool doLock=true, bool isLocked=false)
Construct to guard a Mutex.
Definition: Mutex.h:136
void lock()
Locks the mutex.
Definition: Mutex.h:245
void lock()
Lock the mutex.
Definition: Mutex.h:479
~SpinLock()
Unlocks the mutex unless unlock() was called.
Definition: Mutex.h:534
void unlock()
Unlocks the mutex.
void readLock()
Acquires a read lock.
RecursiveLock(RecursiveMutex &m, bool doLock=true, bool isLocked=false)
Construct to guard a RecursiveMutex.
Definition: Mutex.h:229
MutexLock class for Mutex.
Definition: Mutex.h:126
const Mutex & mutex() const
Returns the guarded the mutex object.
Definition: Mutex.h:177
const RecursiveMutex & mutex() const
Returns the guarded the mutex object.
Definition: Mutex.h:269
WriteLock(ReadWriteMutex &m, bool doLock=true, bool isLocked=false)
Construct to guard a ReadWriteMutex.
Definition: Mutex.h:401
ReadWriteMutex & mutex()
Returns the guarded the mutex object.
Definition: Mutex.h:437
Writer lock object for read-write mutexes.
Definition: Mutex.h:391