00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_spin_rw_mutex_H
00022 #define __TBB_spin_rw_mutex_H
00023
00024 #include "tbb_stddef.h"
00025 #include "tbb_machine.h"
00026 #include "tbb_profiling.h"
00027
00028 namespace tbb {
00029
00030 class spin_rw_mutex_v3;
00031 typedef spin_rw_mutex_v3 spin_rw_mutex;
00032
00034
00035 class spin_rw_mutex_v3 {
00037
00039 bool __TBB_EXPORTED_METHOD internal_acquire_writer();
00040
00042
00043 void __TBB_EXPORTED_METHOD internal_release_writer();
00044
00046 void __TBB_EXPORTED_METHOD internal_acquire_reader();
00047
00049 bool __TBB_EXPORTED_METHOD internal_upgrade();
00050
00052
00053 void __TBB_EXPORTED_METHOD internal_downgrade();
00054
00056 void __TBB_EXPORTED_METHOD internal_release_reader();
00057
00059 bool __TBB_EXPORTED_METHOD internal_try_acquire_writer();
00060
00062 bool __TBB_EXPORTED_METHOD internal_try_acquire_reader();
00063
00065 public:
00067 spin_rw_mutex_v3() : state(0) {
00068 #if TBB_USE_THREADING_TOOLS
00069 internal_construct();
00070 #endif
00071 }
00072
00073 #if TBB_USE_ASSERT
00075 ~spin_rw_mutex_v3() {
00076 __TBB_ASSERT( !state, "destruction of an acquired mutex");
00077 };
00078 #endif
00079
00081
00083 class scoped_lock : internal::no_copy {
00084 public:
00086
00087 scoped_lock() : mutex(NULL), is_writer(false) {}
00088
00090 scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
00091 acquire(m, write);
00092 }
00093
00095 ~scoped_lock() {
00096 if( mutex ) release();
00097 }
00098
00100 void acquire( spin_rw_mutex& m, bool write = true ) {
00101 __TBB_ASSERT( !mutex, "holding mutex already" );
00102 is_writer = write;
00103 mutex = &m;
00104 if( write ) mutex->internal_acquire_writer();
00105 else mutex->internal_acquire_reader();
00106 }
00107
00109
00110 bool upgrade_to_writer() {
00111 __TBB_ASSERT( mutex, "lock is not acquired" );
00112 __TBB_ASSERT( !is_writer, "not a reader" );
00113 is_writer = true;
00114 return mutex->internal_upgrade();
00115 }
00116
00118 void release() {
00119 __TBB_ASSERT( mutex, "lock is not acquired" );
00120 spin_rw_mutex *m = mutex;
00121 mutex = NULL;
00122 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00123 if( is_writer ) m->internal_release_writer();
00124 else m->internal_release_reader();
00125 #else
00126 if( is_writer ) __TBB_AtomicAND( &m->state, READERS );
00127 else __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
00128 #endif
00129 }
00130
00132 bool downgrade_to_reader() {
00133 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00134 __TBB_ASSERT( mutex, "lock is not acquired" );
00135 __TBB_ASSERT( is_writer, "not a writer" );
00136 mutex->internal_downgrade();
00137 #else
00138 __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00139 #endif
00140 is_writer = false;
00141
00142 return true;
00143 }
00144
00146 bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00147 __TBB_ASSERT( !mutex, "holding mutex already" );
00148 bool result;
00149 is_writer = write;
00150 result = write? m.internal_try_acquire_writer()
00151 : m.internal_try_acquire_reader();
00152 if( result )
00153 mutex = &m;
00154 return result;
00155 }
00156
00157 protected:
00159 spin_rw_mutex* mutex;
00160
00162
00163 bool is_writer;
00164 };
00165
00166
00167 static const bool is_rw_mutex = true;
00168 static const bool is_recursive_mutex = false;
00169 static const bool is_fair_mutex = false;
00170
00171
00172
00174 void lock() {internal_acquire_writer();}
00175
00177
00178 bool try_lock() {return internal_try_acquire_writer();}
00179
00181 void unlock() {
00182 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00183 if( state&WRITER ) internal_release_writer();
00184 else internal_release_reader();
00185 #else
00186 if( state&WRITER ) __TBB_AtomicAND( &state, READERS );
00187 else __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00188 #endif
00189 }
00190
00191
00192
00194 void lock_read() {internal_acquire_reader();}
00195
00197
00198 bool try_lock_read() {return internal_try_acquire_reader();}
00199
00200 private:
00201 typedef intptr_t state_t;
00202 static const state_t WRITER = 1;
00203 static const state_t WRITER_PENDING = 2;
00204 static const state_t READERS = ~(WRITER | WRITER_PENDING);
00205 static const state_t ONE_READER = 4;
00206 static const state_t BUSY = WRITER | READERS;
00208
00211 state_t state;
00212
00213 void __TBB_EXPORTED_METHOD internal_construct();
00214 };
00215
00216 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00217
00218 }
00219
00220 #endif