00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_recursive_mutex_H
00022 #define __TBB_recursive_mutex_H
00023
00024 #if _WIN32||_WIN64
00025 #include "machine/windows_api.h"
00026 #else
00027 #include <pthread.h>
00028 #endif
00029
00030 #include <new>
00031 #include "aligned_space.h"
00032 #include "tbb_stddef.h"
00033 #include "tbb_profiling.h"
00034
00035 namespace tbb {
00037
00039 class recursive_mutex {
00040 public:
00042 recursive_mutex() {
00043 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00044 internal_construct();
00045 #else
00046 #if _WIN32||_WIN64
00047 InitializeCriticalSection(&impl);
00048 #else
00049 pthread_mutexattr_t mtx_attr;
00050 int error_code = pthread_mutexattr_init( &mtx_attr );
00051 if( error_code )
00052 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
00053
00054 pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
00055 error_code = pthread_mutex_init( &impl, &mtx_attr );
00056 if( error_code )
00057 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
00058
00059 pthread_mutexattr_destroy( &mtx_attr );
00060 #endif
00061 #endif
00062 };
00063
00064 ~recursive_mutex() {
00065 #if TBB_USE_ASSERT
00066 internal_destroy();
00067 #else
00068 #if _WIN32||_WIN64
00069 DeleteCriticalSection(&impl);
00070 #else
00071 pthread_mutex_destroy(&impl);
00072
00073 #endif
00074 #endif
00075 };
00076
00077 class scoped_lock;
00078 friend class scoped_lock;
00079
00081
00083 class scoped_lock: internal::no_copy {
00084 public:
00086 scoped_lock() : my_mutex(NULL) {};
00087
00089 scoped_lock( recursive_mutex& mutex ) {
00090 #if TBB_USE_ASSERT
00091 my_mutex = &mutex;
00092 #endif
00093 acquire( mutex );
00094 }
00095
00097 ~scoped_lock() {
00098 if( my_mutex )
00099 release();
00100 }
00101
00103 void acquire( recursive_mutex& mutex ) {
00104 #if TBB_USE_ASSERT
00105 internal_acquire( mutex );
00106 #else
00107 my_mutex = &mutex;
00108 mutex.lock();
00109 #endif
00110 }
00111
00113 bool try_acquire( recursive_mutex& mutex ) {
00114 #if TBB_USE_ASSERT
00115 return internal_try_acquire( mutex );
00116 #else
00117 bool result = mutex.try_lock();
00118 if( result )
00119 my_mutex = &mutex;
00120 return result;
00121 #endif
00122 }
00123
00125 void release() {
00126 #if TBB_USE_ASSERT
00127 internal_release();
00128 #else
00129 my_mutex->unlock();
00130 my_mutex = NULL;
00131 #endif
00132 }
00133
00134 private:
00136 recursive_mutex* my_mutex;
00137
00139 void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
00140
00142 bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
00143
00145 void __TBB_EXPORTED_METHOD internal_release();
00146
00147 friend class recursive_mutex;
00148 };
00149
00150
00151 static const bool is_rw_mutex = false;
00152 static const bool is_recursive_mutex = true;
00153 static const bool is_fair_mutex = false;
00154
00155
00156
00158 void lock() {
00159 #if TBB_USE_ASSERT
00160 aligned_space<scoped_lock,1> tmp;
00161 new(tmp.begin()) scoped_lock(*this);
00162 #else
00163 #if _WIN32||_WIN64
00164 EnterCriticalSection(&impl);
00165 #else
00166 pthread_mutex_lock(&impl);
00167 #endif
00168 #endif
00169 }
00170
00172
00173 bool try_lock() {
00174 #if TBB_USE_ASSERT
00175 aligned_space<scoped_lock,1> tmp;
00176 return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
00177 #else
00178 #if _WIN32||_WIN64
00179 return TryEnterCriticalSection(&impl)!=0;
00180 #else
00181 return pthread_mutex_trylock(&impl)==0;
00182 #endif
00183 #endif
00184 }
00185
00187 void unlock() {
00188 #if TBB_USE_ASSERT
00189 aligned_space<scoped_lock,1> tmp;
00190 scoped_lock& s = *tmp.begin();
00191 s.my_mutex = this;
00192 s.internal_release();
00193 #else
00194 #if _WIN32||_WIN64
00195 LeaveCriticalSection(&impl);
00196 #else
00197 pthread_mutex_unlock(&impl);
00198 #endif
00199 #endif
00200 }
00201
00203 #if _WIN32||_WIN64
00204 typedef LPCRITICAL_SECTION native_handle_type;
00205 #else
00206 typedef pthread_mutex_t* native_handle_type;
00207 #endif
00208 native_handle_type native_handle() { return (native_handle_type) &impl; }
00209
00210 private:
00211 #if _WIN32||_WIN64
00212 CRITICAL_SECTION impl;
00213 enum state_t {
00214 INITIALIZED=0x1234,
00215 DESTROYED=0x789A,
00216 } state;
00217 #else
00218 pthread_mutex_t impl;
00219 #endif
00220
00222 void __TBB_EXPORTED_METHOD internal_construct();
00223
00225 void __TBB_EXPORTED_METHOD internal_destroy();
00226 };
00227
00228 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
00229
00230 }
00231
00232 #endif