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 "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 {
00036 
00038 
00040 class mutex {
00041 public:
00043     mutex() {
00044 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
00045     internal_construct();
00046 #else
00047   #if _WIN32||_WIN64
00048         InitializeCriticalSection(&impl);
00049   #else
00050         int error_code = pthread_mutex_init(&impl,NULL);
00051         if( error_code )
00052             tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
00053   #endif 
00054 #endif 
00055     };
00056 
00057     ~mutex() {
00058 #if TBB_USE_ASSERT
00059         internal_destroy();
00060 #else
00061   #if _WIN32||_WIN64
00062         DeleteCriticalSection(&impl);
00063   #else
00064         pthread_mutex_destroy(&impl); 
00065 
00066   #endif 
00067 #endif 
00068     };
00069 
00070     class scoped_lock;
00071     friend class scoped_lock;
00072 
00074 
00076     class scoped_lock : internal::no_copy {
00077     public:
00079         scoped_lock() : my_mutex(NULL) {};
00080 
00082         scoped_lock( mutex& mutex ) {
00083             acquire( mutex );
00084         }
00085 
00087         ~scoped_lock() {
00088             if( my_mutex ) 
00089                 release();
00090         }
00091 
00093         void acquire( mutex& mutex ) {
00094 #if TBB_USE_ASSERT
00095             internal_acquire(mutex);
00096 #else
00097             mutex.lock();
00098             my_mutex = &mutex;
00099 #endif 
00100         }
00101 
00103         bool try_acquire( mutex& mutex ) {
00104 #if TBB_USE_ASSERT
00105             return internal_try_acquire (mutex);
00106 #else
00107             bool result = mutex.try_lock();
00108             if( result )
00109                 my_mutex = &mutex;
00110             return result;
00111 #endif 
00112         }
00113 
00115         void release() {
00116 #if TBB_USE_ASSERT
00117             internal_release ();
00118 #else
00119             my_mutex->unlock();
00120             my_mutex = NULL;
00121 #endif 
00122         }
00123 
00124     private:
00126         mutex* my_mutex;
00127 
00129         void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
00130 
00132         bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
00133 
00135         void __TBB_EXPORTED_METHOD internal_release();
00136 
00137         friend class mutex;
00138     };
00139 
00140     
00141     static const bool is_rw_mutex = false;
00142     static const bool is_recursive_mutex = false;
00143     static const bool is_fair_mutex = false;
00144 
00145     
00146 
00148     void lock() {
00149 #if TBB_USE_ASSERT
00150         aligned_space<scoped_lock,1> tmp;
00151         new(tmp.begin()) scoped_lock(*this);
00152 #else
00153   #if _WIN32||_WIN64
00154         EnterCriticalSection(&impl);
00155   #else
00156         pthread_mutex_lock(&impl);
00157   #endif 
00158 #endif 
00159     }
00160 
00162 
00163     bool try_lock() {
00164 #if TBB_USE_ASSERT
00165         aligned_space<scoped_lock,1> tmp;
00166         scoped_lock& s = *tmp.begin();
00167         s.my_mutex = NULL;
00168         return s.internal_try_acquire(*this);
00169 #else
00170   #if _WIN32||_WIN64
00171         return TryEnterCriticalSection(&impl)!=0;
00172   #else
00173         return pthread_mutex_trylock(&impl)==0;
00174   #endif 
00175 #endif 
00176     }
00177 
00179     void unlock() {
00180 #if TBB_USE_ASSERT
00181         aligned_space<scoped_lock,1> tmp;
00182         scoped_lock& s = *tmp.begin();
00183         s.my_mutex = this;
00184         s.internal_release();
00185 #else
00186   #if _WIN32||_WIN64
00187         LeaveCriticalSection(&impl);
00188   #else
00189         pthread_mutex_unlock(&impl);
00190   #endif 
00191 #endif 
00192     }
00193 
00195   #if _WIN32||_WIN64
00196     typedef LPCRITICAL_SECTION native_handle_type;
00197   #else
00198     typedef pthread_mutex_t* native_handle_type;
00199   #endif
00200     native_handle_type native_handle() { return (native_handle_type) &impl; }
00201 
00202     enum state_t {
00203         INITIALIZED=0x1234,
00204         DESTROYED=0x789A,
00205         HELD=0x56CD
00206     };
00207 private:
00208 #if _WIN32||_WIN64
00209     CRITICAL_SECTION impl;    
00210     enum state_t state;
00211 #else
00212     pthread_mutex_t impl;
00213 #endif 
00214 
00216     void __TBB_EXPORTED_METHOD internal_construct();
00217 
00219     void __TBB_EXPORTED_METHOD internal_destroy();
00220 
00221 #if _WIN32||_WIN64
00222 public:
00224     void set_state( state_t to ) { state = to; }
00225 #endif
00226 };
00227 
00228 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
00229 
00230 } 
00231 
00232 #endif