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 __TBB_ASSERT( mutex, "lock is not acquired" );
00134 __TBB_ASSERT( is_writer, "not a writer" );
00135 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00136 mutex->internal_downgrade();
00137 #else
00138 __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00139 #endif
00140 is_writer = false;
00141 return true;
00142 }
00143
00145 bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00146 __TBB_ASSERT( !mutex, "holding mutex already" );
00147 bool result;
00148 is_writer = write;
00149 result = write? m.internal_try_acquire_writer()
00150 : m.internal_try_acquire_reader();
00151 if( result )
00152 mutex = &m;
00153 return result;
00154 }
00155
00156 protected:
00158 spin_rw_mutex* mutex;
00159
00161
00162 bool is_writer;
00163 };
00164
00165
00166 static const bool is_rw_mutex = true;
00167 static const bool is_recursive_mutex = false;
00168 static const bool is_fair_mutex = false;
00169
00170
00171
00173 void lock() {internal_acquire_writer();}
00174
00176
00177 bool try_lock() {return internal_try_acquire_writer();}
00178
00180 void unlock() {
00181 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00182 if( state&WRITER ) internal_release_writer();
00183 else internal_release_reader();
00184 #else
00185 if( state&WRITER ) __TBB_AtomicAND( &state, READERS );
00186 else __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00187 #endif
00188 }
00189
00190
00191
00193 void lock_read() {internal_acquire_reader();}
00194
00196
00197 bool try_lock_read() {return internal_try_acquire_reader();}
00198
00199 private:
00200 typedef intptr_t state_t;
00201 static const state_t WRITER = 1;
00202 static const state_t WRITER_PENDING = 2;
00203 static const state_t READERS = ~(WRITER | WRITER_PENDING);
00204 static const state_t ONE_READER = 4;
00205 static const state_t BUSY = WRITER | READERS;
00207
00210 state_t state;
00211
00212 void __TBB_EXPORTED_METHOD internal_construct();
00213 };
00214
00215 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00216
00217 }
00218
00219 #endif