00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/MutexImpl.hpp"
00041 #include <cerrno>
00042 #include <cassert>
00043
00044 namespace BLOCXX_NAMESPACE
00045 {
00046
00047 namespace MutexImpl
00048 {
00049
00050 #if defined (BLOCXX_USE_PTHREAD)
00051
00052 #if !defined (BLOCXX_NCR)
00053
00059 int
00060 createMutex(Mutex_t& handle)
00061 {
00062 pthread_mutexattr_t attr;
00063 int res = pthread_mutexattr_init(&attr);
00064 assert(res == 0);
00065 if (res != 0)
00066 {
00067 return -1;
00068 }
00069
00070 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00071 res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00072 assert(res == 0);
00073 if (res != 0)
00074 {
00075 pthread_mutexattr_destroy(&attr);
00076 return -1;
00077 }
00078 #endif
00079
00080 res = pthread_mutex_init(&handle.mutex, &attr);
00081 pthread_mutexattr_destroy(&attr);
00082 if (res != 0)
00083 {
00084 return -1;
00085 }
00086
00087 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00088 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT);
00089 if (res != 0)
00090 {
00091 pthread_mutex_destroy(&handle.mutex);
00092 return -1;
00093 }
00094
00095 handle.valid_id = false;
00096 handle.count = 0;
00097 #endif
00098 return 0;
00099 }
00100
00101 #else //#if !defined (BLOCXX_NCR)
00102
00103 int
00104 createMutex(Mutex_t& handle)
00105 {
00106 pthread_mutexattr_t attr;
00107 int res = pthread_mutexattr_create(&attr);
00108 assert(res == 0);
00109 if (res != 0)
00110 {
00111 return -1;
00112 }
00113
00114 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00115 res = pthread_mutexattr_setkind_np(&attr, MUTEX_RECURSIVE_NP);
00116 assert(res == 0);
00117 if (res != 0)
00118 {
00119 pthread_mutexattr_delete(&attr);
00120 return -1;
00121 }
00122 #endif
00123
00124 res = pthread_mutex_init(&handle.mutex, attr);
00125
00126 pthread_mutexattr_delete(&attr);
00127 if (res != 0)
00128 {
00129 return -1;
00130 }
00131
00132 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00133 res = pthread_cond_init(&handle.unlocked, PTHREAD_COND_ATTR_DEFAULT);
00134 if (res != 0)
00135 {
00136 pthread_mutex_destroy(&handle.mutex);
00137 return -1;
00138 }
00139
00140 handle.valid_id = false;
00141 handle.count = 0;
00142 #endif
00143 return 0;
00144 }
00145
00146 #endif //#ifndef BLOCXX_NCR
00147
00157 int
00158 destroyMutex(Mutex_t& handle)
00159 {
00160 switch (pthread_mutex_destroy(&handle.mutex))
00161 {
00162 case 0:
00163 break;
00164 case EBUSY:
00165 return -1;
00166 break;
00167 default:
00168 return -2;
00169 }
00170 int res = 0;
00171 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00172 res = pthread_cond_destroy(&handle.unlocked);
00173 assert(res == 0);
00174 #endif
00175 return res;
00176 }
00177
00186 int
00187 acquireMutex(Mutex_t& handle)
00188 {
00189 int res = pthread_mutex_lock(&handle.mutex);
00190 assert(res == 0);
00191
00192 #if !defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00193 pthread_t tid = pthread_self();
00194 if (handle.valid_id && pthread_equal(handle.thread_id, tid))
00195 {
00196 ++handle.count;
00197 }
00198 else
00199 {
00200 while (handle.valid_id)
00201 {
00202 res = pthread_cond_wait(&handle.unlocked, &handle.mutex);
00203 assert(res == 0 || res == EINTR);
00204 if (res == EINTR)
00205 {
00206 try
00207 {
00208 Thread::testCancel();
00209 }
00210 catch (...)
00211 {
00212 pthread_mutex_unlock(&handle.mutex);
00213 throw;
00214 }
00215 }
00216 }
00217
00218 handle.thread_id = tid;
00219 handle.valid_id = true;
00220 handle.count = 1;
00221 }
00222
00223 res = pthread_mutex_unlock(&handle.mutex);
00224 assert(res == 0);
00225 #endif
00226 return res;
00227 }
00228
00235 int
00236 releaseMutex(Mutex_t& handle)
00237 {
00238 #if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00239 int res = pthread_mutex_unlock(&handle.mutex);
00240 assert(res == 0);
00241 return res;
00242 #else
00243 int res = 0;
00244 res = pthread_mutex_lock(&handle.mutex);
00245 assert(res == 0);
00246
00247 pthread_t tid = pthread_self();
00248 if (handle.valid_id && !pthread_equal(handle.thread_id, tid))
00249 {
00250 res = pthread_mutex_unlock(&handle.mutex);
00251 assert(res == 0);
00252 return -1;
00253 }
00254
00255 if (--handle.count == 0)
00256 {
00257 assert(handle.valid_id);
00258 handle.valid_id = false;
00259
00260 res = pthread_cond_signal(&handle.unlocked);
00261 assert(res == 0);
00262 }
00263
00264 res = pthread_mutex_unlock(&handle.mutex);
00265 assert(res == 0);
00266 return res;
00267 #endif //#if defined(BLOCXX_HAVE_PTHREAD_MUTEXATTR_SETTYPE)
00268 }
00269
00270 #endif //#if defined (BLOCXX_USE_PTHREAD)
00271
00272 #if defined(BLOCXX_WIN32)
00273
00274 int
00275 createMutex(Mutex_t& handle)
00276 {
00277 handle = new CRITICAL_SECTION;
00278 assert(handle);
00279 InitializeCriticalSection(handle);
00280 return 0;
00281 }
00282
00283 int
00284 destroyMutex(Mutex_t& handle)
00285 {
00286 if(handle)
00287 {
00288 DeleteCriticalSection(handle);
00289 delete handle;
00290 handle = 0;
00291 }
00292 return 0;
00293 }
00294
00295 int
00296 acquireMutex(Mutex_t& handle)
00297 {
00298 EnterCriticalSection(handle);
00299 return 0;
00300 }
00301
00302 int
00303 releaseMutex(Mutex_t& handle)
00304 {
00305 LeaveCriticalSection(handle);
00306 return 0;
00307 }
00308
00309 #endif //#if defined(BLOCXX_WIN32)
00310
00311 }
00312 }
00313