00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef NL_MUTEX_H
00028 #define NL_MUTEX_H
00029
00030 #include "nel/misc/types_nl.h"
00031 #include "nel/misc/time_nl.h"
00032 #include <map>
00033
00034 #ifdef NL_OS_UNIX
00035 #include <pthread.h>
00036 #include <semaphore.h>
00037 #endif
00038
00039 #undef MUTEX_DEBUG
00040
00041
00042 namespace NLMISC {
00043
00044
00045 #define CMutex CFairMutex
00046
00064 class CUnfairMutex
00065 {
00066 public:
00067
00069 CUnfairMutex();
00070 CUnfairMutex(const std::string &name);
00071
00073 ~CUnfairMutex();
00074
00075 void enter ();
00076 void leave ();
00077
00078 private:
00079
00080 #ifdef NL_OS_WINDOWS
00081 void *Mutex;
00082 #elif defined NL_OS_UNIX
00083 pthread_mutex_t mutex;
00084 #else
00085 # error "No unfair mutex implementation for this OS"
00086 #endif
00087
00088 };
00089
00090
00091 #ifdef NL_OS_WINDOWS
00092
00097 struct TNelRtlCriticalSection {
00098 void *DebugInfo;
00099 long LockCount;
00100 long RecursionCount;
00101 void *OwningThread;
00102 void *LockSemaphore;
00103 uint32 SpinCount;
00104 };
00105 #endif // NL_OS_WINDOWS
00106
00107
00131 class CFairMutex
00132 {
00133 public:
00134
00136 CFairMutex();
00137 CFairMutex(const std::string &name);
00138
00140 ~CFairMutex();
00141
00142 void enter ();
00143 void leave ();
00144
00145 std::string Name;
00146
00147 private:
00148
00149 #ifdef NL_OS_WINDOWS
00150 TNelRtlCriticalSection _Cs;
00151 #elif defined NL_OS_UNIX
00152 volatile sem_t _Sem;
00153 #else
00154 # error "No fair mutex implementation for this OS"
00155 #endif
00156
00157
00158 #ifdef MUTEX_DEBUG
00159
00160 void debugCreateMutex();
00161 void debugBeginEnter();
00162 void debugEndEnter();
00163 void debugLeave();
00164 void debugDeleteMutex();
00165 #endif // MUTEX_DEBUG
00166
00167 };
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 #ifdef MUTEX_DEBUG
00178
00179 struct TMutexLocks
00180 {
00181 TMutexLocks(uint32 m=0) : TimeToEnter(0), TimeInMutex(0), Nb(0), WaitingMutex(0), MutexNum(m), ThreadHavingTheMutex(0xFFFFFFFF), Dead(false) {}
00182
00183 uint32 TimeToEnter;
00184 uint32 TimeInMutex;
00185 uint32 Nb;
00186 uint32 WaitingMutex;
00187 sint32 MutexNum;
00188 uint ThreadHavingTheMutex;
00189 bool Dead;
00190 std::string MutexName;
00191
00192 NLMISC::TTicks BeginEnter;
00193 NLMISC::TTicks EndEnter;
00194 };
00195
00197 void initAcquireTimeMap();
00198
00200 std::map<CMutex*,TMutexLocks> getNewAcquireTimes();
00201
00203 extern uint32 NbMutexes;
00204
00205 #endif // MUTEX_DEBUG
00206
00207
00208
00209
00210
00211
00212 #define CSynchronized CFairSynchronized
00213
00235 template <class T>
00236 class CUnfairSynchronized
00237 {
00238 public:
00239
00240 CUnfairSynchronized (const std::string &name) : _Mutex(name) { }
00241
00245 class CAccessor
00246 {
00247 CUnfairSynchronized<T> *Synchronized;
00248 public:
00249
00251 CAccessor(CUnfairSynchronized<T> *cs)
00252 {
00253 Synchronized = cs;
00254 const_cast<CMutex&>(Synchronized->_Mutex).enter();
00255 }
00256
00258 ~CAccessor()
00259 {
00260 const_cast<CMutex&>(Synchronized->_Mutex).leave();
00261 }
00262
00264 T &value()
00265 {
00266 return const_cast<T&>(Synchronized->_Value);
00267 }
00268 };
00269
00270 private:
00271
00272 friend class CUnfairSynchronized::CAccessor;
00273
00275 volatile CUnfairMutex _Mutex;
00276
00278 volatile T _Value;
00279 };
00280
00281
00290 template <class T>
00291 class CFairSynchronized
00292 {
00293 public:
00294
00295 CFairSynchronized (const std::string &name) : _Cs(name) { }
00296
00300 class CAccessor
00301 {
00302 CFairSynchronized<T> *Synchronized;
00303 public:
00304
00306 CAccessor(CFairSynchronized<T> *cs)
00307 {
00308 Synchronized = cs;
00309 const_cast<CFairMutex&>(Synchronized->_Cs).enter();
00310 }
00311
00313 ~CAccessor()
00314 {
00315 const_cast<CFairMutex&>(Synchronized->_Cs).leave();
00316 }
00317
00319 T &value()
00320 {
00321 return const_cast<T&>(Synchronized->_Value);
00322 }
00323 };
00324
00325 private:
00326
00327 friend class CFairSynchronized::CAccessor;
00328
00330 volatile CFairMutex _Cs;
00331
00333 volatile T _Value;
00334 };
00335
00336 }
00337
00338
00339 #endif
00340
00341