csutil/threading/rwmutex.h
00001 /* 00002 (C) Copyright 2006-8 Anthony Williams 00003 00004 Distributed under the Boost Software License, Version 1.0. (See 00005 accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt) 00007 */ 00008 00009 #ifndef __CS_CSUTIL_THREADING_RWMUTEX_H__ 00010 #define __CS_CSUTIL_THREADING_RWMUTEX_H__ 00011 00012 #include "csutil/threading/condition.h" 00013 #include "csutil/threading/mutex.h" 00014 00015 namespace CS 00016 { 00017 namespace Threading 00018 { 00022 class ReadWriteMutex 00023 { 00024 private: 00025 struct StateData 00026 { 00027 unsigned shared_count; 00028 bool exclusive; 00029 bool upgrade; 00030 bool exclusive_waiting_blocked; 00031 00032 StateData() : shared_count(0), 00033 exclusive(false), upgrade(false), 00034 exclusive_waiting_blocked(false) 00035 { 00036 } 00037 }; 00038 00039 StateData state; 00040 Mutex stateChange; 00041 Condition sharedCond; 00042 Condition exclusiveCond; 00043 Condition upgradeCond; 00044 00045 void ReleaseWaiters() 00046 { 00047 exclusiveCond.NotifyOne(); 00048 sharedCond.NotifyAll(); 00049 } 00050 00051 public: 00052 ReadWriteMutex() 00053 { 00054 } 00055 00056 ~ReadWriteMutex() 00057 { 00058 } 00059 00060 void ReadLock() 00061 { 00062 MutexScopedLock lock(stateChange); 00063 00064 while(state.exclusive || state.exclusive_waiting_blocked) 00065 { 00066 sharedCond.Wait(stateChange); 00067 } 00068 ++state.shared_count; 00069 } 00070 00071 void ReadUnlock() 00072 { 00073 MutexScopedLock lock(stateChange); 00074 bool const last_reader=!--state.shared_count; 00075 00076 if(last_reader) 00077 { 00078 if(state.upgrade) 00079 { 00080 state.upgrade=false; 00081 state.exclusive=true; 00082 upgradeCond.NotifyOne(); 00083 } 00084 else 00085 { 00086 state.exclusive_waiting_blocked=false; 00087 } 00088 ReleaseWaiters(); 00089 } 00090 } 00091 00092 void WriteLock() 00093 { 00094 MutexScopedLock lock(stateChange); 00095 00096 while(state.shared_count || state.exclusive) 00097 { 00098 state.exclusive_waiting_blocked=true; 00099 exclusiveCond.Wait(stateChange); 00100 } 00101 state.exclusive=true; 00102 } 00103 00104 void WriteUnlock() 00105 { 00106 MutexScopedLock lock(stateChange); 00107 state.exclusive=false; 00108 state.exclusive_waiting_blocked=false; 00109 ReleaseWaiters(); 00110 } 00111 00112 void UpgradeLock() 00113 { 00114 MutexScopedLock lock(stateChange); 00115 while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) 00116 { 00117 sharedCond.Wait(stateChange); 00118 } 00119 ++state.shared_count; 00120 state.upgrade=true; 00121 } 00122 00123 void UpgradeUnlock() 00124 { 00125 MutexScopedLock lock(stateChange); 00126 state.upgrade=false; 00127 bool const last_reader=!--state.shared_count; 00128 00129 if(last_reader) 00130 { 00131 state.exclusive_waiting_blocked=false; 00132 ReleaseWaiters(); 00133 } 00134 } 00135 00136 void UpgradeUnlockAndWriteLock() 00137 { 00138 MutexScopedLock lock(stateChange); 00139 --state.shared_count; 00140 while(state.shared_count) 00141 { 00142 upgradeCond.Wait(stateChange); 00143 } 00144 state.upgrade=false; 00145 state.exclusive=true; 00146 } 00147 00148 void WriteUnlockAndUpgradeLock() 00149 { 00150 MutexScopedLock lock(stateChange); 00151 state.exclusive=false; 00152 state.upgrade=true; 00153 ++state.shared_count; 00154 state.exclusive_waiting_blocked=false; 00155 ReleaseWaiters(); 00156 } 00157 00158 void WriteUnlockAndReadLock() 00159 { 00160 MutexScopedLock lock(stateChange); 00161 state.exclusive=false; 00162 ++state.shared_count; 00163 state.exclusive_waiting_blocked=false; 00164 ReleaseWaiters(); 00165 } 00166 00167 void UpgradeUnlockAndReadLock() 00168 { 00169 MutexScopedLock lock(stateChange); 00170 state.upgrade=false; 00171 state.exclusive_waiting_blocked=false; 00172 ReleaseWaiters(); 00173 } 00174 }; 00175 00176 class ScopedWriteLock 00177 { 00178 public: 00179 ScopedWriteLock (ReadWriteMutex& lockObj) 00180 : lockObj (lockObj) 00181 { 00182 lockObj.WriteLock (); 00183 } 00184 00185 ~ScopedWriteLock () 00186 { 00187 lockObj.WriteUnlock (); 00188 } 00189 00190 private: 00191 ReadWriteMutex& lockObj; 00192 }; 00193 00194 class ScopedReadLock 00195 { 00196 public: 00197 ScopedReadLock (ReadWriteMutex& lockObj) 00198 : lockObj (lockObj) 00199 { 00200 lockObj.ReadLock (); 00201 } 00202 00203 ~ScopedReadLock () 00204 { 00205 lockObj.ReadUnlock (); 00206 } 00207 00208 private: 00209 ReadWriteMutex& lockObj; 00210 }; 00211 00212 class ScopedUpgradeableLock 00213 { 00214 public: 00215 ScopedUpgradeableLock (ReadWriteMutex& lockObj) 00216 : lockObj (lockObj) 00217 { 00218 lockObj.UpgradeLock (); 00219 } 00220 00221 ~ScopedUpgradeableLock () 00222 { 00223 lockObj.UpgradeUnlock (); 00224 } 00225 00226 private: 00227 ReadWriteMutex& lockObj; 00228 }; 00229 } 00230 } 00231 00232 #endif
Generated for Crystal Space 2.1 by doxygen 1.6.1
