00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _TBB_CRITICAL_SECTION_H_
00022 #define _TBB_CRITICAL_SECTION_H_
00023
00024 #if _WIN32||_WIN64
00025 #include <windows.h>
00026 #else
00027 #include <pthread.h>
00028 #include <errno.h>
00029 #endif // _WIN32||WIN64
00030
00031 #include "tbb_stddef.h"
00032 #include "tbb_thread.h"
00033 #include "tbb_exception.h"
00034
00035 #include "tbb_profiling.h"
00036
00037 namespace tbb {
00038
00039 namespace internal {
00040 class critical_section_v4 : internal::no_copy {
00041 #if _WIN32||_WIN64
00042 CRITICAL_SECTION my_impl;
00043 #else
00044 pthread_mutex_t my_impl;
00045 #endif
00046 tbb_thread::id my_tid;
00047 public:
00048
00049 void __TBB_EXPORTED_METHOD internal_construct();
00050
00051 critical_section_v4() {
00052 #if _WIN32||_WIN64
00053 InitializeCriticalSection(&my_impl);
00054 #else
00055 pthread_mutex_init(&my_impl, NULL);
00056 #endif
00057 internal_construct();
00058 }
00059
00060 ~critical_section_v4() {
00061 __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held critical section");
00062 #if _WIN32||_WIN64
00063 DeleteCriticalSection(&my_impl);
00064 #else
00065 pthread_mutex_destroy(&my_impl);
00066 #endif
00067 }
00068
00069 class scoped_lock : internal::no_copy {
00070 private:
00071 critical_section_v4 &my_crit;
00072 public:
00073 scoped_lock( critical_section_v4& lock_me) :my_crit(lock_me) {
00074 my_crit.lock();
00075 }
00076
00077 ~scoped_lock() {
00078 my_crit.unlock();
00079 }
00080 };
00081
00082 void lock() {
00083 tbb_thread::id local_tid = this_tbb_thread::get_id();
00084 if(local_tid == my_tid) throw_exception( eid_improper_lock );
00085 #if _WIN32||_WIN64
00086 EnterCriticalSection( &my_impl );
00087 #else
00088 int rval = pthread_mutex_lock(&my_impl);
00089 __TBB_ASSERT_EX(!rval, "critical_section::lock: pthread_mutex_lock failed");
00090 #endif
00091 __TBB_ASSERT(my_tid == tbb_thread::id(), NULL);
00092 my_tid = local_tid;
00093 }
00094
00095 bool try_lock() {
00096 bool gotlock;
00097 tbb_thread::id local_tid = this_tbb_thread::get_id();
00098 if(local_tid == my_tid) return false;
00099 #if _WIN32||_WIN64
00100 gotlock = TryEnterCriticalSection( &my_impl ) != 0;
00101 #else
00102 int rval = pthread_mutex_trylock(&my_impl);
00103
00104 __TBB_ASSERT(rval == 0 || rval == EBUSY, "critical_section::trylock: pthread_mutex_trylock failed");
00105 gotlock = rval == 0;
00106 #endif
00107 if(gotlock) {
00108 my_tid = local_tid;
00109 }
00110 return gotlock;
00111 }
00112
00113 void unlock() {
00114 __TBB_ASSERT(this_tbb_thread::get_id() == my_tid, "thread unlocking critical_section is not thread that locked it");
00115 my_tid = tbb_thread::id();
00116 #if _WIN32||_WIN64
00117 LeaveCriticalSection( &my_impl );
00118 #else
00119 int rval = pthread_mutex_unlock(&my_impl);
00120 __TBB_ASSERT_EX(!rval, "critical_section::unlock: pthread_mutex_unlock failed");
00121 #endif
00122 }
00123
00124 static const bool is_rw_mutex = false;
00125 static const bool is_recursive_mutex = false;
00126 static const bool is_fair_mutex = true;
00127 };
00128 }
00129 typedef internal::critical_section_v4 critical_section;
00130
00131 __TBB_DEFINE_PROFILING_SET_NAME(critical_section)
00132 }
00133 #endif // _TBB_CRITICAL_SECTION_H_