MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 - 2014 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 
47 /// @file
48 /// @brief Declares a Mutex, Mutex tools, and at least one MutexLike object.
49 
50 namespace Mezzanine
51 {
52  namespace Threading
53  {
54  /// @brief A mutex like construct that supports multiple readsingle writer semantics and never makes a system call and uses CPU instructions instead.
55  /// @details This should be used when delay is likely to be measured in CPUs cycles and almost
56  /// certainly a short while. For pauses of unknown length use a Mutex so that the OS is informed it
57  /// could schedule another thread.
58  /// @n @n
59  /// Provided readers and writers call the correct functions this will only allow access to a single writer
60  /// or a group of readers at one time
62  {
63  private:
64  /// @internal
65  /// @brief 0 if unlocked, A positive amount is amount of locking readers and a negative value is writed locked.
66  Int32 Locked;
67 
68  public:
69  ///@brief Constructor, creates an unlocked mutex
71  ///@brief Destructor.
73 
74  /// @brief Lock the ReadWriteSpinLock for Reading
75  /// @details The method will block the calling thread until a read lock
76  /// be obtained. This remains locked until @c UnlockRead() is called.
77  /// @n @n
78  /// Multiple read locks can be obtained. If this is locked multiple this
79  /// will keep count until @c UnlockRead() decrements that count.
80  void LockForRead();
81  /// @brief Try to lock this for reading.
82  /// @details The method will try to lock the ReadWriteSpinLock for Reading. If
83  /// it fails, the function will return immediately (non-blocking).
84  /// @return @c true if the lock was acquired, or @c false if the lock could
85  /// not be acquired.
86  bool TryLockForRead();
87  /// @brief Unlock this .
88  /// @details Decrement the reader count and If zero any threads that are waiting
89  /// for the LockWrite method on this mutex, one of them will be unblocked. If
90  /// locked for write, this does nothing.
91  void UnlockRead();
92 
93  /// @brief Lock the ReadWriteSpinLock for Writing.
94  /// @details The method will block the calling thread until a write lock
95  /// be obtained. This remains locked until @c UnlockWrite() is called.
96  /// @n @n
97  /// Only a single write lock can exist and it can co-exist with no read locks.
98  void LockForWrite();
99  /// @brief Try to lock this for writing.
100  /// @details The method will try to lock the ReadWriteSpinLock for writing. If
101  /// it fails, the function will return immediately (non-blocking).
102  /// @return @c true if the lock was acquired, or @c false if the lock could
103  /// not be acquired.
104  bool TryLockForWrite();
105  /// @brief Unlock this for writing.
106  /// @details If any threads are waiting for the read or write lock on this,
107  /// one of them willbe unblocked. If locked for read this doe nothing.
108  void UnlockWrite();
109 
110  /// @brief Simply calls LockForWrite() for compatibility with lock_guard
111  void lock()
112  { LockForWrite(); }
113  /// @brief Simply calls UnlockWrite() for compatibility with lock_guard
114  void unlock()
115  { UnlockWrite(); }
116  };//Mutex
117 
118 
119 
120  /// @brief Read only lock guard.
121  /// @details The constructor locks the mutex, and the destructor unlocks the mutex, so
122  /// the mutex will automatically be unlocked when the lock guard goes out of
123  /// scope. Example usage:
124  /// @code
125  /// ReadWriteSpinLock m;
126  /// ClassThatIsWrittenInAnotherThread n;
127  ///
128  /// ClassThatIsWrittenInAnotherThread GetCurrent()
129  /// {
130  /// ReadOnlyLockGuard<ReadWriteSpinLock> guard(m);
131  /// return n; // returns a copy guaranteed to be valid because
132  /// // the lock (which is attempted in the constructor
133  /// // of the guard) could not be acquired until only
134  /// // readers want it.
135  /// }
136  /// @endcode
137  template <class T>
139  {
140  public:
141  /// @brief This allows other code to use the type of this mutex in a more safe way.
142  typedef T mutex_type;
143 
144  private:
145  /// @internal
146  /// @brief A non-owning pointer to the mutex.
147  mutex_type* mMutex;
148 
149  public:
150  /// @brief The constructor locks the mutex.
151  /// @param aMutex Any mutex which implements lock() and unlock().
152  explicit ReadOnlyLockGuard(mutex_type& aMutex)
153  : mMutex(&aMutex)
154  { mMutex->LockForRead(); }
155 
156  /// @brief The destructor unlocks the mutex.
158  { mMutex->UnlockRead(); }
159  };//lock_guard
160 
161  /// @brief ReadWrite lock guard.
162  /// @details The constructor locks the mutex, and the destructor unlocks the mutex, so
163  /// the mutex will automatically be unlocked when the lock guard goes out of
164  /// scope. Example usage:
165  /// @code
166  /// ReadWriteSpinLock m;
167  /// int counter;
168  ///
169  /// int Increment()
170  /// {
171  /// ReadWriteLockGuard<ReadWriteSpinLock> guard(m);
172  /// return counter++;
173  /// }
174  /// @endcode
175  template <class T>
177  {
178  public:
179  /// @brief This allows other code to use the type of this mutex in a more safe way.
180  typedef T mutex_type;
181 
182  private:
183  /// @internal
184  /// @brief A non-owning pointer to the mutex.
185  mutex_type* mMutex;
186 
187  public:
188  /// @brief The constructor locks the mutex.
189  /// @param aMutex Any mutex which implements lock() and unlock().
190  explicit ReadWriteLockGuard(mutex_type& aMutex)
191  : mMutex(&aMutex)
192  { mMutex->LockForWrite(); }
193 
194  /// @brief The destructor unlocks the mutex.
196  { mMutex->UnlockWrite(); }
197  };//lock_guard
198 
199  }//Threading
200 }//Mezzanine
201 
202 #endif