00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_mutex_H
00022 #define __TBB_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
00032 #else
00033 #include <pthread.h>
00034 namespace tbb { namespace internal {
00035
00036 extern void handle_perror( int error_code, const char* what );
00037 } }
00038 #endif
00039
00040 #include <new>
00041 #include "aligned_space.h"
00042 #include "tbb_stddef.h"
00043 #include "tbb_profiling.h"
00044
00045 namespace tbb {
00046
00048
00050 class mutex {
00051 public:
00053 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 int error_code = pthread_mutex_init(&impl,NULL);
00061 if( error_code )
00062 tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
00063 #endif
00064 #endif
00065 };
00066
00067 ~mutex() {
00068 #if TBB_USE_ASSERT
00069 internal_destroy();
00070 #else
00071 #if _WIN32||_WIN64
00072 DeleteCriticalSection(&impl);
00073 #else
00074 pthread_mutex_destroy(&impl);
00075
00076 #endif
00077 #endif
00078 };
00079
00080 class scoped_lock;
00081 friend class scoped_lock;
00082
00084
00086 class scoped_lock : internal::no_copy {
00087 public:
00089 scoped_lock() : my_mutex(NULL) {};
00090
00092
00093 scoped_lock( mutex& mutex ) {
00094 acquire( mutex );
00095 }
00096
00098 ~scoped_lock() {
00099 if( my_mutex )
00100 release();
00101 }
00102
00104 void acquire( mutex& mutex ) {
00105 #if TBB_USE_ASSERT
00106 internal_acquire(mutex);
00107 #else
00108 mutex.lock();
00109 my_mutex = &mutex;
00110 #endif
00111 }
00112
00114 bool try_acquire( mutex& mutex ) {
00115 #if TBB_USE_ASSERT
00116 return internal_try_acquire (mutex);
00117 #else
00118 bool result = mutex.try_lock();
00119 if( result )
00120 my_mutex = &mutex;
00121 return result;
00122 #endif
00123 }
00124
00126 void release() {
00127 #if TBB_USE_ASSERT
00128 internal_release ();
00129 #else
00130 my_mutex->unlock();
00131 my_mutex = NULL;
00132 #endif
00133 }
00134
00135 private:
00137 mutex* my_mutex;
00138
00140 void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
00141
00143 bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
00144
00146 void __TBB_EXPORTED_METHOD internal_release();
00147
00148 friend class mutex;
00149 };
00150
00151
00152 static const bool is_rw_mutex = false;
00153 static const bool is_recursive_mutex = false;
00154 static const bool is_fair_mutex = false;
00155
00156
00157
00159 void lock() {
00160 #if TBB_USE_ASSERT
00161 aligned_space<scoped_lock,1> tmp;
00162 new(tmp.begin()) scoped_lock(*this);
00163 #else
00164 #if _WIN32||_WIN64
00165 EnterCriticalSection(&impl);
00166 #else
00167 pthread_mutex_lock(&impl);
00168 #endif
00169 #endif
00170 }
00171
00173
00174 bool try_lock() {
00175 #if TBB_USE_ASSERT
00176 aligned_space<scoped_lock,1> tmp;
00177 scoped_lock& s = *tmp.begin();
00178 s.my_mutex = NULL;
00179 return s.internal_try_acquire(*this);
00180 #else
00181 #if _WIN32||_WIN64
00182 return TryEnterCriticalSection(&impl)!=0;
00183 #else
00184 return pthread_mutex_trylock(&impl)==0;
00185 #endif
00186 #endif
00187 }
00188
00190 void unlock() {
00191 #if TBB_USE_ASSERT
00192 aligned_space<scoped_lock,1> tmp;
00193 scoped_lock& s = *tmp.begin();
00194 s.my_mutex = this;
00195 s.internal_release();
00196 #else
00197 #if _WIN32||_WIN64
00198 LeaveCriticalSection(&impl);
00199 #else
00200 pthread_mutex_unlock(&impl);
00201 #endif
00202 #endif
00203 }
00204
00205 private:
00206 #if _WIN32||_WIN64
00207 CRITICAL_SECTION impl;
00208 enum state_t {
00209 INITIALIZED=0x1234,
00210 DESTROYED=0x789A,
00211 HELD=0x56CD
00212 } state;
00213 #else
00214 pthread_mutex_t impl;
00215 #endif
00216
00218 void __TBB_EXPORTED_METHOD internal_construct();
00219
00221 void __TBB_EXPORTED_METHOD internal_destroy();
00222 };
00223
00224 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
00225
00226 }
00227
00228 #endif