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