CrystalSpace

Public API Reference

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.0 by doxygen 1.7.6.1