00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_queuing_rw_mutex_H
00022 #define __TBB_queuing_rw_mutex_H
00023
00024 #include "tbb_config.h"
00025
00026 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00027
00028 #pragma warning (push)
00029 #pragma warning (disable: 4530)
00030 #endif
00031
00032 #include <cstring>
00033
00034 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00035 #pragma warning (pop)
00036 #endif
00037
00038 #include "atomic.h"
00039 #include "tbb_profiling.h"
00040
00041 namespace tbb {
00042
00044
00047 class queuing_rw_mutex {
00048 public:
00050 queuing_rw_mutex() {
00051 q_tail = NULL;
00052 #if TBB_USE_THREADING_TOOLS
00053 internal_construct();
00054 #endif
00055 }
00056
00058 ~queuing_rw_mutex() {
00059 #if TBB_USE_ASSERT
00060 __TBB_ASSERT( !q_tail, "destruction of an acquired mutex");
00061 #endif
00062 }
00063
00065
00067 class scoped_lock: internal::no_copy {
00069 void initialize() {
00070 my_mutex = NULL;
00071 #if TBB_USE_ASSERT
00072 my_state = 0xFF;
00073 internal::poison_pointer(my_next);
00074 internal::poison_pointer(my_prev);
00075 #endif
00076 }
00077
00078 public:
00080
00081 scoped_lock() {initialize();}
00082
00084 scoped_lock( queuing_rw_mutex& m, bool write=true ) {
00085 initialize();
00086 acquire(m,write);
00087 }
00088
00090 ~scoped_lock() {
00091 if( my_mutex ) release();
00092 }
00093
00095 void acquire( queuing_rw_mutex& m, bool write=true );
00096
00098 bool try_acquire( queuing_rw_mutex& m, bool write=true );
00099
00101 void release();
00102
00104
00105 bool upgrade_to_writer();
00106
00108 bool downgrade_to_reader();
00109
00110 private:
00112 queuing_rw_mutex* my_mutex;
00113
00115 scoped_lock *__TBB_atomic my_prev, *__TBB_atomic my_next;
00116
00117 typedef unsigned char state_t;
00118
00120 atomic<state_t> my_state;
00121
00123
00124 unsigned char __TBB_atomic my_going;
00125
00127 unsigned char my_internal_lock;
00128
00130 void acquire_internal_lock();
00131
00133
00134 bool try_acquire_internal_lock();
00135
00137 void release_internal_lock();
00138
00140 void wait_for_release_of_internal_lock();
00141
00143 void unblock_or_wait_on_internal_lock( uintptr_t );
00144 };
00145
00146 void __TBB_EXPORTED_METHOD internal_construct();
00147
00148
00149 static const bool is_rw_mutex = true;
00150 static const bool is_recursive_mutex = false;
00151 static const bool is_fair_mutex = true;
00152
00153 private:
00155 atomic<scoped_lock*> q_tail;
00156
00157 };
00158
00159 __TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex)
00160
00161 }
00162
00163 #endif