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
00064 class scoped_lock;
00065 friend class scoped_lock;
00066
00068
00070 class scoped_lock: internal::no_copy {
00072 void initialize() {
00073 my_mutex = NULL;
00074 #if TBB_USE_ASSERT
00075 my_state = 0xFF;
00076 internal::poison_pointer(my_next);
00077 internal::poison_pointer(my_prev);
00078 #endif
00079 }
00080 public:
00082
00083 scoped_lock() {initialize();}
00084
00086 scoped_lock( queuing_rw_mutex& m, bool write=true ) {
00087 initialize();
00088 acquire(m,write);
00089 }
00090
00092 ~scoped_lock() {
00093 if( my_mutex ) release();
00094 }
00095
00097 void acquire( queuing_rw_mutex& m, bool write=true );
00098
00100 bool try_acquire( queuing_rw_mutex& m, bool write=true );
00101
00103 void release();
00104
00106
00107 bool upgrade_to_writer();
00108
00110 bool downgrade_to_reader();
00111
00112 private:
00114 queuing_rw_mutex* my_mutex;
00115
00117 scoped_lock *__TBB_atomic my_prev, *__TBB_atomic my_next;
00118
00119 typedef unsigned char state_t;
00120
00122 atomic<state_t> my_state;
00123
00125
00126 unsigned char __TBB_atomic my_going;
00127
00129 unsigned char my_internal_lock;
00130
00132 void acquire_internal_lock();
00133
00135
00136 bool try_acquire_internal_lock();
00137
00139 void release_internal_lock();
00140
00142 void wait_for_release_of_internal_lock();
00143
00145 void unblock_or_wait_on_internal_lock( uintptr_t );
00146 };
00147
00148 void __TBB_EXPORTED_METHOD internal_construct();
00149
00150
00151 static const bool is_rw_mutex = true;
00152 static const bool is_recursive_mutex = false;
00153 static const bool is_fair_mutex = true;
00154
00155 private:
00157 atomic<scoped_lock*> q_tail;
00158
00159 };
00160
00161 __TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex)
00162
00163 }
00164
00165 #endif