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
00091 scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
00092 acquire(m, write);
00093 }
00094
00096 ~scoped_lock() {
00097 if( mutex ) release();
00098 }
00099
00101 void acquire( spin_rw_mutex& m, bool write = true ) {
00102 __TBB_ASSERT( !mutex, "holding mutex already" );
00103 is_writer = write;
00104 mutex = &m;
00105 if( write ) mutex->internal_acquire_writer();
00106 else mutex->internal_acquire_reader();
00107 }
00108
00110
00111 bool upgrade_to_writer() {
00112 __TBB_ASSERT( mutex, "lock is not acquired" );
00113 __TBB_ASSERT( !is_writer, "not a reader" );
00114 is_writer = true;
00115 return mutex->internal_upgrade();
00116 }
00117
00119 void release() {
00120 __TBB_ASSERT( mutex, "lock is not acquired" );
00121 spin_rw_mutex *m = mutex;
00122 mutex = NULL;
00123 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00124 if( is_writer ) m->internal_release_writer();
00125 else m->internal_release_reader();
00126 #else
00127 if( is_writer ) __TBB_AtomicAND( &m->state, READERS );
00128 else __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
00129 #endif
00130 }
00131
00133 bool downgrade_to_reader() {
00134 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00135 __TBB_ASSERT( mutex, "lock is not acquired" );
00136 __TBB_ASSERT( is_writer, "not a writer" );
00137 mutex->internal_downgrade();
00138 #else
00139 __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00140 #endif
00141 is_writer = false;
00142
00143 return true;
00144 }
00145
00147 bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00148 __TBB_ASSERT( !mutex, "holding mutex already" );
00149 bool result;
00150 is_writer = write;
00151 result = write? m.internal_try_acquire_writer()
00152 : m.internal_try_acquire_reader();
00153 if( result )
00154 mutex = &m;
00155 return result;
00156 }
00157
00158 private:
00160 spin_rw_mutex* mutex;
00161
00163
00164 bool is_writer;
00165 };
00166
00167
00168 static const bool is_rw_mutex = true;
00169 static const bool is_recursive_mutex = false;
00170 static const bool is_fair_mutex = false;
00171
00172
00173
00175 void lock() {internal_acquire_writer();}
00176
00178
00179 bool try_lock() {return internal_try_acquire_writer();}
00180
00182 void unlock() {
00183 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00184 if( state&WRITER ) internal_release_writer();
00185 else internal_release_reader();
00186 #else
00187 if( state&WRITER ) __TBB_AtomicAND( &state, READERS );
00188 else __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00189 #endif
00190 }
00191
00192
00193
00195 void lock_read() {internal_acquire_reader();}
00196
00198
00199 bool try_lock_read() {return internal_try_acquire_reader();}
00200
00201 private:
00202 typedef intptr_t state_t;
00203 static const state_t WRITER = 1;
00204 static const state_t WRITER_PENDING = 2;
00205 static const state_t READERS = ~(WRITER | WRITER_PENDING);
00206 static const state_t ONE_READER = 4;
00207 static const state_t BUSY = WRITER | READERS;
00209
00212 state_t state;
00213
00214 void __TBB_EXPORTED_METHOD internal_construct();
00215 };
00216
00217 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00218
00219 }
00220
00221 #endif