Spinning Topp Logo BlackTopp Studios
inc
readwritespinlock.h
Go to the documentation of this file.
1 // The DAGFrameScheduler is a Multi-Threaded lock free and wait free scheduling library.
2 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
3 /* This file is part of The DAGFrameScheduler.
4 
5  The DAGFrameScheduler is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  The DAGFrameScheduler is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with The DAGFrameScheduler. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /* The original authors have included a copy of the license specified above in the
19  'doc' folder. See 'gpl.txt'
20 */
21 /* We welcome the use of the DAGFrameScheduler to anyone, including companies who wish to
22  Build professional software and charge for their product.
23 
24  However there are some practical restrictions, so if your project involves
25  any of the following you should contact us and we will try to work something
26  out:
27  - DRM or Copy Protection of any kind(except Copyrights)
28  - Software Patents You Do Not Wish to Freely License
29  - Any Kind of Linking to Non-GPL licensed Works
30  - Are Currently In Violation of Another Copyright Holder's GPL License
31  - If You want to change our code and not add a few hundred MB of stuff to
32  your distribution
33 
34  These and other limitations could cause serious legal problems if you ignore
35  them, so it is best to simply contact us or the Free Software Foundation, if
36  you have any questions.
37 
38  Joseph Toppi - toppij@gmail.com
39  John Blackwood - makoenergy02@gmail.com
40 */
41 #ifndef _readwritespinlock_h
42 #define _readwritespinlock_h
43 
44 #include "datatypes.h"
45 #include "lockguard.h"
46 #include "spinlock.h"
47 
48 /// @file
49 /// @brief Declares a Mutex, Mutex tools, and at least one MutexLike object.
50 
51 namespace Mezzanine
52 {
53  namespace Threading
54  {
55  /// @brief A mutex like construct that supports multiple readsingle writer semantics and never makes a system call and uses CPU instructions instead.
56  /// @details This should be used when delay is likely to be measured in CPUs cycles and almost
57  /// certainly a short while. For pauses of unknown length use a Mutex so that the OS is informed it
58  /// could schedule another thread.
59  /// @n @n
60  /// Provided readers and writers call the correct functions this will only allow access to a single writer
61  /// or a group of readers at one time
63  {
64  private:
65  /// @brief Used to synchronize access to Locked, to indicate either the current count of Read locks or the existence of write locks
66  SpinLock CountGaurd;
67 
68  /// @internal
69  /// @brief 0 if unlocked, A positive amount is amount of locking readers and a negative value is writed locked.
70  Int32 Locked;
71 
72  public:
73  ///@brief Constructor, creates an unlocked mutex
75  ///@brief Destructor.
77 
78  /// @brief Lock the ReadWriteSpinLock for Reading
79  /// @details The method will block the calling thread until a read lock
80  /// be obtained. This remains locked until @c UnlockRead() is called.
81  /// @n @n
82  /// Multiple read locks can be obtained. If this is locked multiple this
83  /// will keep count until @c UnlockRead() decrements that count.
84  void LockForRead();
85  /// @brief Try to lock this for reading.
86  /// @details The method will try to lock the ReadWriteSpinLock for Reading. If
87  /// it fails, the function will return immediately (non-blocking).
88  /// @return @c true if the lock was acquired, or @c false if the lock could
89  /// not be acquired.
90  bool TryLockForRead();
91  /// @brief Unlock this .
92  /// @details Decrement the reader count and If zero any threads that are waiting
93  /// for the LockWrite method on this mutex, one of them will be unblocked. If
94  /// locked for write, this does nothing.
95  void UnlockRead();
96 
97  /// @brief Lock the ReadWriteSpinLock for Writing.
98  /// @details The method will block the calling thread until a write lock
99  /// be obtained. This remains locked until @c UnlockWrite() is called.
100  /// @n @n
101  /// Only a single write lock can exist and it can co-exist with no read locks.
102  void LockForWrite();
103  /// @brief Try to lock this for writing.
104  /// @details The method will try to lock the ReadWriteSpinLock for writing. If
105  /// it fails, the function will return immediately (non-blocking).
106  /// @return @c true if the lock was acquired, or @c false if the lock could
107  /// not be acquired.
108  bool TryLockForWrite();
109  /// @brief Unlock this for writing.
110  /// @details If any threads are waiting for the read or write lock on this,
111  /// one of them willbe unblocked. If locked for read this doe nothing.
112  void UnlockWrite();
113 
114  /// @brief Simply calls LockForWrite() for compatibility with lock_guard
115  void lock()
116  { LockForWrite(); }
117  /// @brief Simply calls UnlockWrite() for compatibility with lock_guard
118  void unlock()
119  { UnlockWrite(); }
120  };//Mutex
121 
122 
123 
124  /// @brief Read only lock guard.
125  /// @details The constructor locks the mutex, and the destructor unlocks the mutex, so
126  /// the mutex will automatically be unlocked when the lock guard goes out of
127  /// scope. Example usage:
128  /// @code
129  /// ReadWriteSpinLock m;
130  /// ClassThatIsWrittenInAnotherThread n;
131  ///
132  /// ClassThatIsWrittenInAnotherThread GetCurrent()
133  /// {
134  /// ReadOnlyLockGuard<ReadWriteSpinLock> guard(m);
135  /// return n; // returns a copy guaranteed to be valid because
136  /// // the lock (which is attempted in the constructor
137  /// // of the guard) could not be acquired until only
138  /// // readers want it.
139  /// }
140  /// @endcode
141  template <class T>
143  {
144  public:
145  /// @brief This allows other code to use the type of this mutex in a more safe way.
146  typedef T mutex_type;
147 
148  private:
149  /// @internal
150  /// @brief A non-owning pointer to the mutex.
151  mutex_type* mMutex;
152 
153  public:
154  /// @brief The constructor locks the mutex.
155  /// @param aMutex Any mutex which implements lock() and unlock().
156  explicit ReadOnlyLockGuard(mutex_type& aMutex)
157  : mMutex(&aMutex)
158  { mMutex->LockForRead(); }
159 
160  /// @brief The destructor unlocks the mutex.
162  { mMutex->UnlockRead(); }
163  };//lock_guard
164 
165  /// @brief ReadWrite lock guard.
166  /// @details The constructor locks the mutex, and the destructor unlocks the mutex, so
167  /// the mutex will automatically be unlocked when the lock guard goes out of
168  /// scope. Example usage:
169  /// @code
170  /// ReadWriteSpinLock m;
171  /// int counter;
172  ///
173  /// int Increment()
174  /// {
175  /// ReadWriteLockGuard<ReadWriteSpinLock> guard(m);
176  /// return counter++;
177  /// }
178  /// @endcode
179  template <class T>
181  {
182  public:
183  /// @brief This allows other code to use the type of this mutex in a more safe way.
184  typedef T mutex_type;
185 
186  private:
187  /// @internal
188  /// @brief A non-owning pointer to the mutex.
189  mutex_type* mMutex;
190 
191  public:
192  /// @brief The constructor locks the mutex.
193  /// @param aMutex Any mutex which implements lock() and unlock().
194  explicit ReadWriteLockGuard(mutex_type& aMutex)
195  : mMutex(&aMutex)
196  { mMutex->LockForWrite(); }
197 
198  /// @brief The destructor unlocks the mutex.
200  { mMutex->UnlockWrite(); }
201  };//lock_guard
202 
203  }//Threading
204 }//Mezzanine
205 
206 #endif
int32_t Int32
An 32-bit integer.
Definition: datatypes.h:124
void unlock()
Simply calls UnlockWrite() for compatibility with lock_guard.
~ReadOnlyLockGuard()
The destructor unlocks the mutex.
ReadOnlyLockGuard(mutex_type &aMutex)
The constructor locks the mutex.
Declares a Mutex, Mutex tools, and at least one MutexLike object.
All the definitions for datatypes as well as some basic conversion functions are defined here...
ReadWriteLockGuard(mutex_type &aMutex)
The constructor locks the mutex.
void lock()
Simply calls LockForWrite() for compatibility with lock_guard.
Declares a tool for automatically unlocking a mutex in an exception safe way.
T mutex_type
This allows other code to use the type of this mutex in a more safe way.
A mutex like construct that never makes a system call and uses CPU instructions instead.
Definition: spinlock.h:83
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
T mutex_type
This allows other code to use the type of this mutex in a more safe way.
A mutex like construct that supports multiple readsingle writer semantics and never makes a system ca...
~ReadWriteLockGuard()
The destructor unlocks the mutex.