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