00001
00002
00003
00004
00005
00006
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