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 <cstring>
00025 #include "atomic.h"
00026 #include "tbb_profiling.h"
00027
00028 namespace tbb {
00029
00031
00034 class queuing_rw_mutex {
00035 public:
00037 queuing_rw_mutex() {
00038 q_tail = NULL;
00039 #if TBB_USE_THREADING_TOOLS
00040 internal_construct();
00041 #endif
00042 }
00043
00045 ~queuing_rw_mutex() {
00046 #if TBB_USE_ASSERT
00047 __TBB_ASSERT( !q_tail, "destruction of an acquired mutex");
00048 #endif
00049 }
00050
00051 class scoped_lock;
00052 friend class scoped_lock;
00053
00055
00057 class scoped_lock: internal::no_copy {
00059 void initialize() {
00060 mutex = NULL;
00061 #if TBB_USE_ASSERT
00062 state = 0xFF;
00063 internal::poison_pointer(next);
00064 internal::poison_pointer(prev);
00065 #endif
00066 }
00067 public:
00069
00070 scoped_lock() {initialize();}
00071
00073
00074 scoped_lock( queuing_rw_mutex& m, bool write=true ) {
00075 initialize();
00076 acquire(m,write);
00077 }
00078
00080 ~scoped_lock() {
00081 if( mutex ) release();
00082 }
00083
00085 void acquire( queuing_rw_mutex& m, bool write=true );
00086
00088 bool try_acquire( queuing_rw_mutex& m, bool write=true );
00089
00091 void release();
00092
00094
00095 bool upgrade_to_writer();
00096
00098 bool downgrade_to_reader();
00099
00100 private:
00102 queuing_rw_mutex* mutex;
00103
00105 scoped_lock * prev, * next;
00106
00107 typedef unsigned char state_t;
00108
00110 atomic<state_t> state;
00111
00113
00114 unsigned char going;
00115
00117 unsigned char internal_lock;
00118
00120 void acquire_internal_lock();
00121
00123
00124 bool try_acquire_internal_lock();
00125
00127 void release_internal_lock();
00128
00130 void wait_for_release_of_internal_lock();
00131
00133 void unblock_or_wait_on_internal_lock( uintptr_t );
00134 };
00135
00136 void __TBB_EXPORTED_METHOD internal_construct();
00137
00138
00139 static const bool is_rw_mutex = true;
00140 static const bool is_recursive_mutex = false;
00141 static const bool is_fair_mutex = true;
00142
00143 private:
00145 atomic<scoped_lock*> q_tail;
00146
00147 };
00148
00149 __TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex)
00150
00151 }
00152
00153 #endif