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
00027 namespace tbb {
00028
00029 class spin_rw_mutex_v3;
00030 typedef spin_rw_mutex_v3 spin_rw_mutex;
00031
00033
00034 class spin_rw_mutex_v3 {
00036
00038 bool internal_acquire_writer();
00039
00041
00042 void internal_release_writer();
00043
00045 void internal_acquire_reader();
00046
00048 bool internal_upgrade();
00049
00051
00052 void internal_downgrade();
00053
00055 void internal_release_reader();
00056
00058 bool internal_try_acquire_writer();
00059
00061 bool internal_try_acquire_reader();
00062
00064 public:
00066 spin_rw_mutex_v3() : state(0) {}
00067
00068 #if TBB_DO_ASSERT
00069
00070 ~spin_rw_mutex_v3() {
00071 __TBB_ASSERT( !state, "destruction of an acquired mutex");
00072 };
00073 #endif
00074
00076
00078 class scoped_lock : private internal::no_copy {
00079 public:
00081
00082 scoped_lock() : mutex(NULL) {}
00083
00085
00086 scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
00087 acquire(m, write);
00088 }
00089
00091 ~scoped_lock() {
00092 if( mutex ) release();
00093 }
00094
00096 void acquire( spin_rw_mutex& m, bool write = true ) {
00097 __TBB_ASSERT( !mutex, "holding mutex already" );
00098 is_writer = write;
00099 mutex = &m;
00100 if( write ) mutex->internal_acquire_writer();
00101 else mutex->internal_acquire_reader();
00102 }
00103
00105
00106 bool upgrade_to_writer() {
00107 __TBB_ASSERT( mutex, "lock is not acquired" );
00108 __TBB_ASSERT( !is_writer, "not a reader" );
00109 is_writer = true;
00110 return mutex->internal_upgrade();
00111 }
00112
00114 void release() {
00115 __TBB_ASSERT( mutex, "lock is not acquired" );
00116 spin_rw_mutex *m = mutex;
00117 mutex = NULL;
00118 #if TBB_DO_THREADING_TOOLS||TBB_DO_ASSERT
00119 if( is_writer ) m->internal_release_writer();
00120 else m->internal_release_reader();
00121 #else
00122 if( is_writer ) __TBB_AtomicAND( &m->state, READERS );
00123 else __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
00124 #endif
00125 }
00126
00128 bool downgrade_to_reader() {
00129 #if TBB_DO_THREADING_TOOLS||TBB_DO_ASSERT
00130 __TBB_ASSERT( mutex, "lock is not acquired" );
00131 __TBB_ASSERT( is_writer, "not a writer" );
00132 mutex->internal_downgrade();
00133 #else
00134 __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00135 #endif
00136 is_writer = false;
00137
00138 return true;
00139 }
00140
00142 bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00143 __TBB_ASSERT( !mutex, "holding mutex already" );
00144 bool result;
00145 is_writer = write;
00146 result = write? m.internal_try_acquire_writer()
00147 : m.internal_try_acquire_reader();
00148 if( result )
00149 mutex = &m;
00150 return result;
00151 }
00152
00153 private:
00155 spin_rw_mutex* mutex;
00156
00158
00159 bool is_writer;
00160 };
00161
00162
00163 static const bool is_rw_mutex = true;
00164 static const bool is_recursive_mutex = false;
00165 static const bool is_fair_mutex = false;
00166
00167 private:
00168 typedef intptr_t state_t;
00169 static const state_t WRITER = 1;
00170 static const state_t WRITER_PENDING = 2;
00171 static const state_t READERS = ~(WRITER | WRITER_PENDING);
00172 static const state_t ONE_READER = 4;
00173 static const state_t BUSY = WRITER | READERS;
00175
00178 state_t state;
00179 };
00180
00181 }
00182
00183 #endif