MPMA Framework 0.4
|
00001 00002 //Luke Lenhart, 2007 00003 //See /docs/License.txt for details on how this code may be used. 00004 00005 #include "Types.h" 00006 #include "ReferenceCount.h" 00007 00008 #include <set> 00009 00010 #ifndef LOCKS_H_INCLUDED 00011 #define LOCKS_H_INCLUDED 00012 00013 namespace MPMA 00014 { 00015 00016 // -- Atomic Operations safe for multiprocessor operations 00017 00019 void AtomicIntInc(volatile nuint *pint); 00020 00022 void AtomicIntDec(volatile nuint *pint); 00023 00025 nsint AtomicIntAdd(volatile nsint *pint, nsint addValue); 00026 00028 bool AtomicCompareExchange(volatile nuint *pInt, nuint expectedValue, nuint newValue, volatile nuint &outResultValue); 00029 00031 template <typename T> inline bool AtomicCompareExchange(T **ptrToReplace, T *ptrExpected, T *ptrToSet, T *&outResultValue) { return AtomicCompareExchange((nuint*)ptrToReplace, (nuint)ptrExpected, (nuint)ptrToSet, (nuint&)outResultValue); } 00032 00033 // -- Locking constructs 00034 00035 //used by MutexLock 00036 struct InternalMutexLockData 00037 { 00038 void *crit; 00039 }; 00040 00042 class MutexLock: public ReferenceCountedData<InternalMutexLockData> 00043 { 00044 public: 00045 MutexLock(); 00046 ~MutexLock(); 00047 00048 friend class TakeMutexLock; 00049 }; 00050 00052 class TakeMutexLock 00053 { 00054 public: 00056 TakeMutexLock(MutexLock &critSection, bool takeNow=true); 00058 ~TakeMutexLock(); 00059 00061 void Take(); 00063 void Leave(); 00064 00065 private: 00066 MutexLock crit; 00067 bool taken; 00068 00069 //you cannot duplicate this 00070 TakeMutexLock(const TakeMutexLock&); 00071 const TakeMutexLock& operator=(const TakeMutexLock&); 00072 }; 00073 00074 00075 //used by SpinLock 00076 struct InternalSpinLockData 00077 { 00078 volatile nuint taken; 00079 bool collision; 00080 00081 inline InternalSpinLockData(): taken(0), collision(false) 00082 {} 00083 }; 00084 00086 class SpinLock: public ReferenceCountedData<InternalSpinLockData> 00087 { 00088 friend class TakeSpinLock; 00089 }; 00090 00092 class TakeSpinLock 00093 { 00094 public: 00096 inline TakeSpinLock(SpinLock &slock, bool takeNow=true): locker(slock), taken(false) 00097 { if (takeNow) Take(); } 00099 inline ~TakeSpinLock() 00100 { Leave(); } 00101 00103 inline void Take(); 00105 inline void Leave(); 00106 00107 private: 00108 SpinLock locker; 00109 bool taken; 00110 00111 //you cannot duplicate this 00112 TakeSpinLock(const TakeSpinLock&); 00113 const TakeSpinLock& operator=(const TakeSpinLock&); 00114 }; 00115 00116 //used by RWSleepLock 00117 struct InternalRWSleepLockData 00118 { 00119 volatile nuint readerCount; 00120 volatile nuint writerCount; 00121 00122 std::multiset<nuint> readerThreadList; 00123 std::multiset<nuint> writerThreadList; 00124 SpinLock threadListLock; 00125 00126 inline InternalRWSleepLockData(): readerCount(0), writerCount(0) 00127 {} 00128 }; 00129 00132 class RWSleepLock: public ReferenceCountedData<InternalRWSleepLockData> 00133 { 00134 public: 00135 friend class TakeRWSleepLock; 00136 }; 00137 00139 class TakeRWSleepLock 00140 { 00141 public: 00143 TakeRWSleepLock(RWSleepLock &rwsLock, bool writeAccessIfTakenNow=true, bool takeNow=true); 00145 ~TakeRWSleepLock(); 00146 00148 void TakeWrite(); 00150 void LeaveWrite(); 00151 00153 void TakeRead(); 00155 void LeaveRead(); 00156 00157 private: 00158 RWSleepLock lock; 00159 00160 bool hasRead, hasWrite; 00161 00162 //you cannot duplicate this 00163 TakeRWSleepLock(const TakeRWSleepLock&); 00164 const TakeRWSleepLock& operator=(const TakeRWSleepLock&); 00165 }; 00166 00167 // -- Signal-based blocking constructs 00168 00169 struct InternalBlockingObjectData 00170 { 00171 InternalBlockingObjectData(); 00172 ~InternalBlockingObjectData(); 00173 00174 volatile int clearCount; 00175 volatile bool isSet; 00176 void *pdata; //platform-specific container 00177 }; 00178 00180 class BlockingObject: public ReferenceCountedData<InternalBlockingObjectData> 00181 { 00182 public: 00184 void Clear(); 00185 00187 void Set(); 00188 00190 bool WaitUntilClear(bool setOnReturn=false, nuint timeToWait=0xffffffff); 00191 }; 00192 00193 } //namespace MPMA 00194 00195 //include the templated and inline code 00196 #ifndef LOCKS_INCLUDE_INLINE 00197 #define LOCKS_INCLUDE_INLINE 00198 #include "Locks.cpp" 00199 #endif 00200 00201 //include the platform-specific headers 00202 #if defined(_WIN32) || defined(_WIN64) 00203 #include "win32/LocksWin32.h" 00204 #else 00205 #include "linux/LocksLin32.h" 00206 #endif 00207 00208 #endif //LOCKS_H_INCLUDED