csutil/threading/pthread_mutex.h
00001 /* 00002 Copyright (C) 2006 by Marten Svanfeldt 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 isLocked = false; 00044 } 00045 00046 void Destroy () 00047 { 00048 pthread_mutex_destroy (&mutex); 00049 } 00050 00051 bool IsLocked () 00052 { 00053 return isLocked; 00054 } 00055 00056 bool Lock () 00057 { 00058 int status = pthread_mutex_lock (&mutex); 00059 isLocked = (status == 0); 00060 return isLocked; 00061 } 00062 00063 bool TryLock () 00064 { 00065 int status = pthread_mutex_trylock (&mutex); 00066 isLocked = (status == 0); 00067 return isLocked; 00068 } 00069 00070 void Unlock () 00071 { 00072 pthread_mutex_unlock (&mutex); 00073 } 00074 00075 protected: 00076 friend class ConditionBase; 00077 00078 pthread_mutex_t mutex; 00079 bool isLocked; 00080 }; 00081 00082 00086 #ifdef CS_PTHREAD_MUTEX_RECURSIVE 00087 class RecursiveMutexBase : public MutexBase 00088 { 00089 public: 00090 void Initialize () 00091 { 00092 // Use different initialization 00093 pthread_mutexattr_t attr; 00094 pthread_mutexattr_init (&attr); 00095 pthread_mutexattr_settype (&attr, CS_PTHREAD_MUTEX_RECURSIVE); 00096 pthread_mutex_init (&mutex, &attr); 00097 } 00098 }; 00099 #else 00100 00101 // Recursive mutex when native recursive mutex isn't supported by pthread 00102 // Emulate it 00103 class RecursiveMutexBase : public MutexBase 00104 { 00105 public: 00106 void Initialize () 00107 { 00108 MutexBase::Initialize (); 00109 00110 recursionCount = 0; 00111 validID = false; 00112 pthread_cond_init (&unlockedCond, 0); 00113 } 00114 00115 void Destroy () 00116 { 00117 MutexBase::Destroy (); 00118 pthread_cond_destroy (&unlockedCond); 00119 } 00120 00121 bool IsLocked () 00122 { 00123 bool ret = false; 00124 MutexBase::Lock (); 00125 00126 if (validID && recursionCount > 0) 00127 { 00128 ret = true; 00129 } 00130 00131 MutexBase::Unlock (); 00132 return ret; 00133 } 00134 00135 bool Lock () 00136 { 00137 MutexBase::Lock (); 00138 00139 pthread_t tid = pthread_self (); 00140 if (validID && pthread_equal (threadID, tid)) 00141 { 00142 ++recursionCount; 00143 } 00144 else 00145 { 00146 while (validID) 00147 { 00148 pthread_cond_wait (&unlockedCond, &mutex); 00149 } 00150 00151 threadID = tid; 00152 validID = true; 00153 recursionCount = 1; 00154 } 00155 00156 MutexBase::Unlock (); 00157 } 00158 00159 bool TryLock () 00160 { 00161 bool ret = false; 00162 MutexBase::Lock (); 00163 00164 pthread_t tid = pthread_self (); 00165 if (validID && pthread_equal (threadID, tid)) 00166 { 00167 ++recursionCount; 00168 ret = true; 00169 } 00170 else if (!validID) 00171 { 00172 threadID = tid; 00173 validID = true; 00174 recursionCount = 1; 00175 ret = true; 00176 } 00177 00178 MutexBase::Unlock (); 00179 return ret; 00180 } 00181 00182 void Unlock () 00183 { 00184 MutexBase::Lock (); 00185 pthread_t tid = pthread_self (); 00186 if (validID && !pthread_equal (threadID, tid)) 00187 { 00188 MutexBase::Unlock (); 00189 return; 00190 } 00191 00192 if (--recursionCount == 0) 00193 { 00194 validID = false; 00195 pthread_cond_signal (&unlockedCond); 00196 } 00197 00198 MutexBase::Unlock (); 00199 } 00200 00201 protected: 00202 pthread_cond_t unlockedCond; 00203 pthread_t threadID; 00204 int32 recursionCount; 00205 bool validID; 00206 }; 00207 00208 #endif 00209 00210 } // namespace Implementation 00211 } // namespace Threading 00212 } // namespace CS 00213 00214 #endif // DOXYGEN_RUN 00215 00216 #endif // __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__
Generated for Crystal Space 1.2 by doxygen 1.4.7