mutex.H

Go to the documentation of this file.
00001 #ifndef mutex_header
00002 #define mutex_header
00003 
00011 // possible problem:
00012 // LinuxThreads have various non-POSIX types of mutexes. Default mutex type
00013 // is "fast": On "unlock()" it is not checked, whether the caller is the
00014 // owner of the mutex! So any thread can unlock the mutex. You shouldn't
00015 // rely on this "feature". In fact, it has a very serious drawback: In a
00016 // try-catch block you must know the exact state of the mutex, otherwise
00017 // other threads may sneak into critical sections or a deadlock occurs!
00018 
00019 
00020 extern "C"
00021 {
00022  #include <pthread.h>
00023 }
00024 
00025 #include "utils.H"
00026 
00027 
00029 class CMutex : private ForbidAssignment
00030 {
00031  private: 
00032   pthread_mutex_t mutex;
00033  public:
00034   inline CMutex()
00035    {
00036      pthread_mutex_init(&mutex,NULL);
00037    }
00038   inline ~CMutex()
00039    {
00040 #ifndef DEBUG
00041      pthread_mutex_destroy(&mutex);
00042 #else /* only for debugging */
00043      const int result = pthread_mutex_destroy(&mutex);
00044      if (result==EBUSY)
00045       {
00046         using std::cerr; using std::endl;
00047         cerr << "cannot destroy busy mutex!!" << endl;
00048         exit(1);
00049       }
00050 #endif
00051    }
00052   inline void lock()
00053    {
00054      const int result = pthread_mutex_lock(&mutex);
00055      switch (result)
00056       {
00057         using std::cerr; using std::endl;
00058         case EINVAL:
00059           cerr << "the mutex has not been properly initialized." << endl;
00060           exit(1);
00061         case EDEADLK:
00062           cerr << "the mutex is already locked by the calling thread" << endl;
00063           exit(1);
00064       }
00065    }
00066   inline bool trylock()
00067    {
00068      const int result = pthread_mutex_trylock(&mutex);
00069      switch (result)
00070       {
00071         using std::cerr; using std::endl;
00072         case EINVAL:
00073           cerr << "the mutex has not been properly initialized." << endl;
00074           exit(1);
00075         case EBUSY:
00076 #ifdef VERBOSE
00077           cerr << "the mutex could not be acquired because it was currently locked." << endl;
00078 #endif
00079           return false;
00080       }
00081      return true;
00082    }
00083   inline void unlock()
00084    {
00085      const int result = pthread_mutex_unlock(&mutex);
00086      switch (result)
00087       {
00088         using std::cerr; using std::endl;
00089         case EINVAL:
00090           cerr << "the mutex has not been properly initialized." << endl;
00091           exit(1);
00092         case EPERM:
00093           cerr << "the calling thread does not own the mutex" << endl;
00094           exit(1);
00095         case EBUSY:
00096           cerr << "the mutex is currently locked." << endl;
00097           exit(1);
00098       }
00099    }
00100 };
00101 
00102 
00111 class CUnlockMutexAtDestruction : private ForbidAssignment
00112 {
00113  private:
00114   CMutex &mutex;
00115  public:
00116   CUnlockMutexAtDestruction(CMutex &myMutex) : mutex(myMutex) { }
00117   ~CUnlockMutexAtDestruction() { mutex.unlock(); }
00118 };
00119 
00120 
00129 class CConditionalUnlockMutexAtDestruction : private ForbidAssignment
00130 {
00131  private:
00132   CMutex &mutex;
00133   bool condition;
00134  public:
00135   CConditionalUnlockMutexAtDestruction(CMutex &myMutex, const bool initial_condition)
00136    : mutex(myMutex), condition(initial_condition) { }
00137   ~CConditionalUnlockMutexAtDestruction() { if (condition) mutex.unlock(); }
00138   void set_condition(const bool new_condition = true) { condition=new_condition; }
00139 };
00140 
00141 
00155 class CCriticalSection : private ForbidAssignment
00156 {
00157  public:
00158   class Mutex : private CMutex // private inheritance to forbid usage outside this class
00159    {
00160      friend class CCriticalSection; // the owning class is allowed to call methods!
00161    };
00162 
00163  private:
00164   Mutex &mutex;
00165   bool inside;
00166 
00167  public:
00168 
00170   inline void enter()
00171    {
00172 #ifdef DEBUG
00173      if (inside) std::cerr << "CCriticalSection::enter():  already entered" << std::endl;
00174 #endif
00175      if (!inside) mutex.lock(); // enter the critical section (wait until mutex can be obtained)
00176      inside=true;
00177    }
00178 
00180   inline bool try_enter()
00181    {
00182 #ifdef DEBUG
00183      if (inside) std::cerr << "CCriticalSection::enter():  already entered" << std::endl;
00184 #endif
00185      if (!inside) inside=mutex.trylock(); // try to enter the critical section (but don't wait if mutex cannot be obtained)
00186      return inside;
00187    }
00188 
00190   inline void leave()
00191    {
00192 #ifdef DEBUG
00193      if (!inside) std::cerr << "CCriticalSection::leave():  already left" << std::endl;
00194 #endif
00195      if (inside) mutex.unlock();
00196      inside=false;
00197    }
00198 
00200   CCriticalSection(CCriticalSection::Mutex &crit_sect_mutex, const bool enter_now=true)
00201    : mutex(crit_sect_mutex), inside(false)
00202    {
00203      if (enter_now) enter(); // enter the critical section
00204    }
00205 
00207   ~CCriticalSection()
00208    {
00209      if (inside) leave(); // leave the critical section
00210    }
00211 
00212 };
00213 
00214 #endif

Generated on Wed Nov 7 23:29:25 2007 for Qsieve by  doxygen 1.5.4