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 <windows.h>
00026 #if !defined(_WIN32_WINNT)
00027
00028
00029 extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
00030 #endif
00031 #else
00032 #include <pthread.h>
00033 #endif
00034
00035 #include <new>
00036 #include "aligned_space.h"
00037 #include "tbb_stddef.h"
00038 #include "tbb_profiling.h"
00039
00040 namespace tbb {
00042
00044 class recursive_mutex {
00045 public:
00047 recursive_mutex() {
00048 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00049 internal_construct();
00050 #else
00051 #if _WIN32||_WIN64
00052 InitializeCriticalSection(&impl);
00053 #else
00054 pthread_mutexattr_t mtx_attr;
00055 int error_code = pthread_mutexattr_init( &mtx_attr );
00056 if( error_code )
00057 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
00058
00059 pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
00060 error_code = pthread_mutex_init( &impl, &mtx_attr );
00061 if( error_code )
00062 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
00063
00064 pthread_mutexattr_destroy( &mtx_attr );
00065 #endif
00066 #endif
00067 };
00068
00069 ~recursive_mutex() {
00070 #if TBB_USE_ASSERT
00071 internal_destroy();
00072 #else
00073 #if _WIN32||_WIN64
00074 DeleteCriticalSection(&impl);
00075 #else
00076 pthread_mutex_destroy(&impl);
00077
00078 #endif
00079 #endif
00080 };
00081
00082 class scoped_lock;
00083 friend class scoped_lock;
00084
00086
00088 class scoped_lock: internal::no_copy {
00089 public:
00091 scoped_lock() : my_mutex(NULL) {};
00092
00094 scoped_lock( recursive_mutex& mutex ) {
00095 #if TBB_USE_ASSERT
00096 my_mutex = &mutex;
00097 #endif
00098 acquire( mutex );
00099 }
00100
00102 ~scoped_lock() {
00103 if( my_mutex )
00104 release();
00105 }
00106
00108 void acquire( recursive_mutex& mutex ) {
00109 #if TBB_USE_ASSERT
00110 internal_acquire( mutex );
00111 #else
00112 my_mutex = &mutex;
00113 mutex.lock();
00114 #endif
00115 }
00116
00118 bool try_acquire( recursive_mutex& mutex ) {
00119 #if TBB_USE_ASSERT
00120 return internal_try_acquire( mutex );
00121 #else
00122 bool result = mutex.try_lock();
00123 if( result )
00124 my_mutex = &mutex;
00125 return result;
00126 #endif
00127 }
00128
00130 void release() {
00131 #if TBB_USE_ASSERT
00132 internal_release();
00133 #else
00134 my_mutex->unlock();
00135 my_mutex = NULL;
00136 #endif
00137 }
00138
00139 private:
00141 recursive_mutex* my_mutex;
00142
00144 void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
00145
00147 bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
00148
00150 void __TBB_EXPORTED_METHOD internal_release();
00151
00152 friend class recursive_mutex;
00153 };
00154
00155
00156 static const bool is_rw_mutex = false;
00157 static const bool is_recursive_mutex = true;
00158 static const bool is_fair_mutex = false;
00159
00160
00161
00163 void lock() {
00164 #if TBB_USE_ASSERT
00165 aligned_space<scoped_lock,1> tmp;
00166 new(tmp.begin()) scoped_lock(*this);
00167 #else
00168 #if _WIN32||_WIN64
00169 EnterCriticalSection(&impl);
00170 #else
00171 pthread_mutex_lock(&impl);
00172 #endif
00173 #endif
00174 }
00175
00177
00178 bool try_lock() {
00179 #if TBB_USE_ASSERT
00180 aligned_space<scoped_lock,1> tmp;
00181 return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
00182 #else
00183 #if _WIN32||_WIN64
00184 return TryEnterCriticalSection(&impl)!=0;
00185 #else
00186 return pthread_mutex_trylock(&impl)==0;
00187 #endif
00188 #endif
00189 }
00190
00192 void unlock() {
00193 #if TBB_USE_ASSERT
00194 aligned_space<scoped_lock,1> tmp;
00195 scoped_lock& s = *tmp.begin();
00196 s.my_mutex = this;
00197 s.internal_release();
00198 #else
00199 #if _WIN32||_WIN64
00200 LeaveCriticalSection(&impl);
00201 #else
00202 pthread_mutex_unlock(&impl);
00203 #endif
00204 #endif
00205 }
00206
00208 #if _WIN32||_WIN64
00209 typedef LPCRITICAL_SECTION native_handle_type;
00210 #else
00211 typedef pthread_mutex_t* native_handle_type;
00212 #endif
00213 native_handle_type native_handle() { return (native_handle_type) &impl; }
00214
00215 private:
00216 #if _WIN32||_WIN64
00217 CRITICAL_SECTION impl;
00218 enum state_t {
00219 INITIALIZED=0x1234,
00220 DESTROYED=0x789A,
00221 } state;
00222 #else
00223 pthread_mutex_t impl;
00224 #endif
00225
00227 void __TBB_EXPORTED_METHOD internal_construct();
00228
00230 void __TBB_EXPORTED_METHOD internal_destroy();
00231 };
00232
00233 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
00234
00235 }
00236
00237 #endif