File indexing completed on 2025-01-18 10:12:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_spin_rw_mutex_H
0018 #define __TBB_spin_rw_mutex_H
0019
0020 #include "tbb_stddef.h"
0021 #include "tbb_machine.h"
0022 #include "tbb_profiling.h"
0023 #include "internal/_mutex_padding.h"
0024
0025 namespace tbb {
0026
0027 #if __TBB_TSX_AVAILABLE
0028 namespace interface8 { namespace internal {
0029 class x86_rtm_rw_mutex;
0030 }}
0031 #endif
0032
0033 class spin_rw_mutex_v3;
0034 typedef spin_rw_mutex_v3 spin_rw_mutex;
0035
0036
0037
0038 class spin_rw_mutex_v3 : internal::mutex_copy_deprecated_and_disabled {
0039
0040
0041
0042 bool __TBB_EXPORTED_METHOD internal_acquire_writer();
0043
0044
0045
0046 void __TBB_EXPORTED_METHOD internal_release_writer();
0047
0048
0049 void __TBB_EXPORTED_METHOD internal_acquire_reader();
0050
0051
0052 bool __TBB_EXPORTED_METHOD internal_upgrade();
0053
0054
0055
0056 void __TBB_EXPORTED_METHOD internal_downgrade();
0057
0058
0059 void __TBB_EXPORTED_METHOD internal_release_reader();
0060
0061
0062 bool __TBB_EXPORTED_METHOD internal_try_acquire_writer();
0063
0064
0065 bool __TBB_EXPORTED_METHOD internal_try_acquire_reader();
0066
0067
0068 public:
0069
0070 spin_rw_mutex_v3() : state(0) {
0071 #if TBB_USE_THREADING_TOOLS
0072 internal_construct();
0073 #endif
0074 }
0075
0076 #if TBB_USE_ASSERT
0077
0078 ~spin_rw_mutex_v3() {
0079 __TBB_ASSERT( !state, "destruction of an acquired mutex");
0080 };
0081 #endif
0082
0083
0084
0085
0086 class scoped_lock : internal::no_copy {
0087 #if __TBB_TSX_AVAILABLE
0088 friend class tbb::interface8::internal::x86_rtm_rw_mutex;
0089 #endif
0090 public:
0091
0092
0093 scoped_lock() : mutex(NULL), is_writer(false) {}
0094
0095
0096 scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
0097 acquire(m, write);
0098 }
0099
0100
0101 ~scoped_lock() {
0102 if( mutex ) release();
0103 }
0104
0105
0106 void acquire( spin_rw_mutex& m, bool write = true ) {
0107 __TBB_ASSERT( !mutex, "holding mutex already" );
0108 is_writer = write;
0109 mutex = &m;
0110 if( write ) mutex->internal_acquire_writer();
0111 else mutex->internal_acquire_reader();
0112 }
0113
0114
0115
0116 bool upgrade_to_writer() {
0117 __TBB_ASSERT( mutex, "mutex is not acquired" );
0118 if (is_writer) return true;
0119 is_writer = true;
0120 return mutex->internal_upgrade();
0121 }
0122
0123
0124 void release() {
0125 __TBB_ASSERT( mutex, "mutex is not acquired" );
0126 spin_rw_mutex *m = mutex;
0127 mutex = NULL;
0128 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
0129 if( is_writer ) m->internal_release_writer();
0130 else m->internal_release_reader();
0131 #else
0132 if( is_writer ) __TBB_AtomicAND( &m->state, READERS );
0133 else __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
0134 #endif
0135 }
0136
0137
0138 bool downgrade_to_reader() {
0139 __TBB_ASSERT( mutex, "mutex is not acquired" );
0140 if (!is_writer) return true;
0141 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
0142 mutex->internal_downgrade();
0143 #else
0144 __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
0145 #endif
0146 is_writer = false;
0147 return true;
0148 }
0149
0150
0151 bool try_acquire( spin_rw_mutex& m, bool write = true ) {
0152 __TBB_ASSERT( !mutex, "holding mutex already" );
0153 bool result;
0154 is_writer = write;
0155 result = write? m.internal_try_acquire_writer()
0156 : m.internal_try_acquire_reader();
0157 if( result )
0158 mutex = &m;
0159 return result;
0160 }
0161
0162 protected:
0163
0164
0165 spin_rw_mutex* mutex;
0166
0167
0168
0169 bool is_writer;
0170 };
0171
0172
0173 static const bool is_rw_mutex = true;
0174 static const bool is_recursive_mutex = false;
0175 static const bool is_fair_mutex = false;
0176
0177
0178
0179
0180 void lock() {internal_acquire_writer();}
0181
0182
0183
0184 bool try_lock() {return internal_try_acquire_writer();}
0185
0186
0187 void unlock() {
0188 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
0189 if( state&WRITER ) internal_release_writer();
0190 else internal_release_reader();
0191 #else
0192 if( state&WRITER ) __TBB_AtomicAND( &state, READERS );
0193 else __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
0194 #endif
0195 }
0196
0197
0198
0199
0200 void lock_read() {internal_acquire_reader();}
0201
0202
0203
0204 bool try_lock_read() {return internal_try_acquire_reader();}
0205
0206 protected:
0207 typedef intptr_t state_t;
0208 static const state_t WRITER = 1;
0209 static const state_t WRITER_PENDING = 2;
0210 static const state_t READERS = ~(WRITER | WRITER_PENDING);
0211 static const state_t ONE_READER = 4;
0212 static const state_t BUSY = WRITER | READERS;
0213
0214
0215
0216
0217 state_t state;
0218
0219 private:
0220 void __TBB_EXPORTED_METHOD internal_construct();
0221 };
0222
0223 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
0224
0225 }
0226
0227 #if __TBB_TSX_AVAILABLE
0228 #include "internal/_x86_rtm_rw_mutex_impl.h"
0229 #endif
0230
0231 namespace tbb {
0232 namespace interface8 {
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 #if __TBB_TSX_AVAILABLE
0243 typedef interface7::internal::padded_mutex<tbb::interface8::internal::x86_rtm_rw_mutex,true> speculative_spin_rw_mutex;
0244 #else
0245 typedef interface7::internal::padded_mutex<tbb::spin_rw_mutex,true> speculative_spin_rw_mutex;
0246 #endif
0247 }
0248
0249 using interface8::speculative_spin_rw_mutex;
0250 __TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_rw_mutex)
0251 }
0252 #endif