# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mutex.h

Go to the documentation of this file.
00001 
00008 /* Copyright, 2000 Nevrax Ltd.
00009  *
00010  * This file is part of NEVRAX NEL.
00011  * NEVRAX NEL is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2, or (at your option)
00014  * any later version.
00015 
00016  * NEVRAX NEL is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019  * General Public License for more details.
00020 
00021  * You should have received a copy of the GNU General Public License
00022  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00023  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00024  * MA 02111-1307, USA.
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 // By default, all mutex use the CFairMutex class to avoid freeze problem.
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;        // from the thread's ClientId->UniqueThread
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         // debug stuffs
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  * Debug info
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;                    // cumulated time blocking on enter
00184         uint32          TimeInMutex;                    // cumulated time between enter and leave
00185         uint32          Nb;                                             // number of calls of enter
00186         uint32          WaitingMutex;                   // number of thread that waiting this mutex
00187     sint32              MutexNum;                               // identifying a mutex
00188         uint            ThreadHavingTheMutex;   // thread id of the thread that is in this mutex (0xFFFFFFFF if no thread)
00189         bool            Dead;                                   // True if the mutex is dead (deleted)
00190         std::string     MutexName;                              // Name of the mutex
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 // By default, all synchronization use the CFairSynchronized class to avoid freeze problem.
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 } // NLMISC
00337 
00338 
00339 #endif // NL_MUTEX_H
00340 
00341 /* End of mutex.h */