Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #pragma once
00015
00019 #ifdef KNET_USE_BOOST
00020 #include <boost/thread/recursive_mutex.hpp>
00021 #include <boost/thread/thread.hpp>
00022 #elif WIN32
00023 #include <Windows.h>
00024 #else
00025 #error No Mutex implementation available!
00026 #endif
00027
00028 #include "PolledTimer.h"
00029 #include "NetworkLogging.h"
00030
00031 namespace kNet
00032 {
00033
00034 template<typename T>
00035 class Lockable;
00036
00039 template<typename T>
00040 class Lock
00041 {
00042 public:
00043 explicit Lock(Lockable<T> *lockedObject_)
00044 :lockedObject(lockedObject_), value(&lockedObject->LockGet())
00045 {
00046 }
00047
00048 Lock(const Lock<T> &rhs)
00049 :lockedObject(rhs.lockedObject), value(rhs.value)
00050 {
00051 assert(this != &rhs);
00052 rhs.TearDown();
00053 }
00054
00055 Lock<T> &operator=(const Lock<T> &rhs)
00056 {
00057 if (&rhs == this)
00058 return *this;
00059
00060 lockedObject = rhs.lockedObject();
00061 value = rhs.value;
00062
00063 rhs.TearDown();
00064 }
00065
00066 ~Lock()
00067 {
00068 Unlock();
00069 }
00070
00071 void Unlock()
00072 {
00073 if (lockedObject)
00074 {
00075 lockedObject->Unlock();
00076 lockedObject = 0;
00077 }
00078 }
00079
00080 T *operator ->() const { return value; }
00081 T &operator *() { return *value; }
00082
00083 private:
00084 mutable Lockable<T> *lockedObject;
00085 mutable T *value;
00086
00089 void TearDown() const { lockedObject = 0; value = 0; }
00090 };
00091
00094 template<typename T>
00095 class ConstLock
00096 {
00097 public:
00098 explicit ConstLock(const Lockable<T> *lockedObject_)
00099 :lockedObject(lockedObject_), value(&lockedObject->LockGet())
00100 {
00101 }
00102
00103 ConstLock(const ConstLock<T> &rhs)
00104 :lockedObject(rhs.lockedObject), value(rhs.value)
00105 {
00106 assert(this != &rhs);
00107 rhs.TearDown();
00108 }
00109
00110 ConstLock<T> &operator=(const ConstLock<T> &rhs)
00111 {
00112 if (&rhs == this)
00113 return *this;
00114
00115 lockedObject = rhs.lockedObject();
00116 value = rhs.value;
00117
00118 rhs.TearDown();
00119 }
00120
00121 ~ConstLock()
00122 {
00123 if (lockedObject)
00124 lockedObject->Unlock();
00125 }
00126
00127 const T *operator ->() const { return value; }
00128 const T &operator *() const { return *value; }
00129
00130 private:
00131 mutable const Lockable<T> *lockedObject;
00132 mutable const T *value;
00133
00136 void TearDown() const { lockedObject = 0; value = 0; }
00137 };
00138
00141 template<typename T>
00142 class Lockable
00143 {
00144 public:
00145 typedef Lock<T> LockType;
00146 typedef ConstLock<T> ConstLockType;
00147
00148 Lockable()
00149 {
00150 #if defined(WIN32) && !defined(KNET_USE_BOOST)
00151 InitializeCriticalSection(&lockObject);
00152 #endif
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162 explicit Lockable(const T &value_)
00163 :value(value_)
00164 {
00165 #if defined(WIN32) && !defined(KNET_USE_BOOST)
00166 InitializeCriticalSection(&lockObject);
00167 #endif
00168 }
00169
00170 ~Lockable()
00171 {
00172 #if defined(WIN32) && !defined(KNET_USE_BOOST)
00173 DeleteCriticalSection(&lockObject);
00174 #endif
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 T &LockGet()
00189 {
00190 #ifdef KNET_USE_BOOST
00191 boostMutex.lock();
00192 #elif WIN32
00193 EnterCriticalSection(&lockObject);
00194 #endif
00195 return value;
00196 }
00197
00198 const T &LockGet() const
00199 {
00200 #ifdef KNET_USE_BOOST
00201 boostMutex.lock();
00202 #elif WIN32
00203 EnterCriticalSection(&lockObject);
00204 #endif
00205 return value;
00206 }
00207
00208 void Unlock() const
00209 {
00210 #ifdef KNET_USE_BOOST
00211 boostMutex.unlock();
00212 #elif WIN32
00213 LeaveCriticalSection(&lockObject);
00214 #endif
00215 }
00216
00217 LockType Acquire()
00218 {
00219 return LockType(this);
00220 }
00221
00222 ConstLockType Acquire() const
00223 {
00224 return ConstLockType(this);
00225 }
00226
00231 T &UnsafeGetValue()
00232 {
00233 return value;
00234 }
00235
00240 const T &UnsafeGetValue() const
00241 {
00242 return value;
00243 }
00244
00245 #ifdef KNET_USE_BOOST
00246 mutable boost::recursive_mutex boostMutex;
00247 #elif WIN32
00248 mutable CRITICAL_SECTION lockObject;
00249 #endif
00250
00251 private:
00252 T value;
00253
00254 void operator=(const Lockable<T> &);
00255 Lockable(const Lockable<T> &);
00256 };
00257
00258 }