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
00026 #include <windows.h>
00027 #if !defined(_WIN32_WINNT)
00028
00029
00030 extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
00031 #endif
00032
00033 #else
00034
00035 #include <pthread.h>
00036 namespace tbb { namespace internal {
00037
00038 extern void handle_perror( int error_code, const char* what );
00039 } }
00040
00041 #endif
00042
00043 #include "tbb_stddef.h"
00044 #include "tbb_profiling.h"
00045
00046 namespace tbb {
00048
00050 class recursive_mutex {
00051 public:
00053 recursive_mutex() {
00054 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00055 internal_construct();
00056 #else
00057 #if _WIN32||_WIN64
00058 InitializeCriticalSection(&impl);
00059 #else
00060 pthread_mutexattr_t mtx_attr;
00061 int error_code = pthread_mutexattr_init( &mtx_attr );
00062 if( error_code )
00063 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
00064
00065 pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
00066 error_code = pthread_mutex_init( &impl, &mtx_attr );
00067 if( error_code )
00068 tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
00069
00070 pthread_mutexattr_destroy( &mtx_attr );
00071 #endif
00072 #endif
00073 };
00074
00075 ~recursive_mutex() {
00076 #if TBB_USE_ASSERT
00077 internal_destroy();
00078 #else
00079 #if _WIN32||_WIN64
00080 DeleteCriticalSection(&impl);
00081 #else
00082 pthread_mutex_destroy(&impl);
00083
00084 #endif
00085 #endif
00086 };
00087
00088 class scoped_lock;
00089 friend class scoped_lock;
00090
00092
00094 class scoped_lock: internal::no_copy {
00095 public:
00097 scoped_lock() : my_mutex(NULL) {};
00098
00100
00101 scoped_lock( recursive_mutex& mutex ) {
00102 acquire( mutex );
00103 }
00104
00106 ~scoped_lock() {
00107 if( my_mutex )
00108 release();
00109 }
00110
00112 void acquire( recursive_mutex& mutex ) {
00113 #if TBB_USE_ASSERT
00114 internal_acquire( mutex );
00115 #else
00116 my_mutex = &mutex;
00117 #if _WIN32||_WIN64
00118 EnterCriticalSection(&mutex.impl);
00119 #else
00120 pthread_mutex_lock( &mutex.impl );
00121 #endif
00122 #endif
00123 }
00124
00126 bool try_acquire( recursive_mutex& mutex ) {
00127 #if TBB_USE_ASSERT
00128 return internal_try_acquire( mutex );
00129 #else
00130 bool result;
00131 #if _WIN32||_WIN64
00132 result = TryEnterCriticalSection(&mutex.impl)!=0;
00133 #else
00134 result = pthread_mutex_trylock(&mutex.impl)==0;
00135 #endif
00136 if( result )
00137 my_mutex = &mutex;
00138
00139 return result;
00140 #endif
00141 }
00142
00144 void release() {
00145 #if TBB_USE_ASSERT
00146 internal_release ();
00147 #else
00148 #if _WIN32||_WIN64
00149 LeaveCriticalSection(&my_mutex->impl);
00150 #else
00151 pthread_mutex_unlock(&my_mutex->impl);
00152 #endif
00153 my_mutex = NULL;
00154 #endif
00155 }
00156
00157 private:
00159 recursive_mutex* my_mutex;
00160
00162 void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
00163
00165 bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
00166
00168 void __TBB_EXPORTED_METHOD internal_release();
00169 };
00170
00171
00172 static const bool is_rw_mutex = false;
00173 static const bool is_recursive_mutex = true;
00174 static const bool is_fair_mutex = false;
00175
00176 private:
00177 #if _WIN32||_WIN64
00178 CRITICAL_SECTION impl;
00179 enum state_t {
00180 INITIALIZED=0x1234,
00181 DESTROYED=0x789A,
00182 } state;
00183 #else
00184 pthread_mutex_t impl;
00185 #endif
00186
00188 void __TBB_EXPORTED_METHOD internal_construct();
00189
00191 void __TBB_EXPORTED_METHOD internal_destroy();
00192 };
00193
00194 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
00195
00196 }
00197
00198 #endif