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