00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__
00020 #define __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__
00021
00022 #ifndef DOXYGEN_RUN
00023
00024 #include <pthread.h>
00025
00026 namespace CS
00027 {
00028 namespace Threading
00029 {
00030 namespace Implementation
00031 {
00032 class ConditionBase;
00033
00037 class MutexBase
00038 {
00039 public:
00040 void Initialize ()
00041 {
00042 pthread_mutex_init (&mutex, 0);
00043 }
00044
00045 void Destroy ()
00046 {
00047 pthread_mutex_destroy (&mutex);
00048 }
00049
00050 bool Lock ()
00051 {
00052 int status = pthread_mutex_lock (&mutex);
00053 return status == 0;
00054 }
00055
00056 bool TryLock ()
00057 {
00058 int status = pthread_mutex_trylock (&mutex);
00059 return status == 0;
00060 }
00061
00062 void Unlock ()
00063 {
00064 pthread_mutex_unlock (&mutex);
00065 }
00066
00067 protected:
00068 friend class ConditionBase;
00069
00070 pthread_mutex_t mutex;
00071 };
00072
00073
00077 #ifdef CS_PTHREAD_MUTEX_RECURSIVE
00078 class RecursiveMutexBase : public MutexBase
00079 {
00080 public:
00081 void Initialize ()
00082 {
00083
00084 pthread_mutexattr_t attr;
00085 pthread_mutexattr_init (&attr);
00086 pthread_mutexattr_settype (&attr, CS_PTHREAD_MUTEX_RECURSIVE);
00087 pthread_mutex_init (&mutex, &attr);
00088 }
00089 };
00090 #else
00091
00092
00093
00094 class RecursiveMutexBase : public MutexBase
00095 {
00096 public:
00097 void Initialize ()
00098 {
00099 MutexBase::Initialize ();
00100
00101 recursionCount = 0;
00102 validID = false;
00103 pthread_cond_init (&unlockedCond, 0);
00104 }
00105
00106 void Destroy ()
00107 {
00108 MutexBase::Destroy ();
00109 pthread_cond_destroy (&unlockedCond);
00110 }
00111
00112 bool Lock ()
00113 {
00114 MutexBase::Lock ();
00115
00116 pthread_t tid = pthread_self ();
00117 if (validID && pthread_equal (threadID, tid))
00118 {
00119 ++recursionCount;
00120 }
00121 else
00122 {
00123 while (validID)
00124 {
00125 pthread_cond_wait (&unlockedCond, &mutex);
00126 }
00127
00128 threadID = tid;
00129 validID = true;
00130 recursionCount = 1;
00131 }
00132
00133 MutexBase::Unlock ();
00134 }
00135
00136 bool TryLock ()
00137 {
00138 bool ret = false;
00139 MutexBase::Lock ();
00140
00141 pthread_t tid = pthread_self ();
00142 if (validID && pthread_equal (threadID, tid))
00143 {
00144 ++recursionCount;
00145 ret = true;
00146 }
00147 else if (!validID)
00148 {
00149 threadID = tid;
00150 validID = true;
00151 recursionCount = 1;
00152 ret = true;
00153 }
00154
00155 MutexBase::Unlock ();
00156 return ret;
00157 }
00158
00159 void Unlock ()
00160 {
00161 MutexBase::Lock ();
00162 pthread_t tid = pthread_self ();
00163 if (validID && !pthread_equal (threadID, tid))
00164 {
00165 MutexBase::Unlock ();
00166 return;
00167 }
00168
00169 if (--recursionCount == 0)
00170 {
00171 validID = false;
00172 pthread_cond_signal (&unlockedCond);
00173 }
00174
00175 MutexBase::Unlock ();
00176 }
00177
00178 protected:
00179 pthread_cond_t unlockedCond;
00180 pthread_t threadID;
00181 int32 recursionCount;
00182 bool validID;
00183 };
00184
00185 #endif
00186
00187 }
00188 }
00189 }
00190
00191 #endif // DOXYGEN_RUN
00192
00193 #endif // __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__