MCPcopy Create free account
hub / github.com/cameron314/concurrentqueue / acquire

Method acquire

benchmarks/tbb/queuing_rw_mutex.cpp:144–227  ·  view source on GitHub ↗

A method to acquire queuing_rw_mutex lock

Source from the content-addressed store, hash-verified

142
143//! A method to acquire queuing_rw_mutex lock
144void queuing_rw_mutex::scoped_lock::acquire( queuing_rw_mutex& m, bool write )
145{
146 __TBB_ASSERT( !my_mutex, "scoped_lock is already holding a mutex");
147
148 // Must set all fields before the fetch_and_store, because once the
149 // fetch_and_store executes, *this becomes accessible to other threads.
150 my_mutex = &m;
151 __TBB_store_relaxed(my_prev , (scoped_lock*)0);
152 __TBB_store_relaxed(my_next , (scoped_lock*)0);
153 __TBB_store_relaxed(my_going, 0);
154 my_state = state_t(write ? STATE_WRITER : STATE_READER);
155 my_internal_lock = RELEASED;
156
157 queuing_rw_mutex::scoped_lock* pred = m.q_tail.fetch_and_store<tbb::release>(this);
158
159 if( write ) { // Acquiring for write
160
161 if( pred ) {
162 ITT_NOTIFY(sync_prepare, my_mutex);
163 pred = tricky_pointer(pred) & ~FLAG;
164 __TBB_ASSERT( !( uintptr_t(pred) & FLAG ), "use of corrupted pointer!" );
165#if TBB_USE_ASSERT
166 __TBB_control_consistency_helper(); // on "m.q_tail"
167 __TBB_ASSERT( !__TBB_load_relaxed(pred->my_next), "the predecessor has another successor!");
168#endif
169 __TBB_store_with_release(pred->my_next,this);
170 spin_wait_until_eq(my_going, 1);
171 }
172
173 } else { // Acquiring for read
174#if DO_ITT_NOTIFY
175 bool sync_prepare_done = false;
176#endif
177 if( pred ) {
178 unsigned short pred_state;
179 __TBB_ASSERT( !__TBB_load_relaxed(my_prev), "the predecessor is already set" );
180 if( uintptr_t(pred) & FLAG ) {
181 /* this is only possible if pred is an upgrading reader and it signals us to wait */
182 pred_state = STATE_UPGRADE_WAITING;
183 pred = tricky_pointer(pred) & ~FLAG;
184 } else {
185 // Load pred->my_state now, because once pred->my_next becomes
186 // non-NULL, we must assume that *pred might be destroyed.
187 pred_state = pred->my_state.compare_and_swap<tbb::acquire>(STATE_READER_UNBLOCKNEXT, STATE_READER);
188 }
189 __TBB_store_relaxed(my_prev, pred);
190 __TBB_ASSERT( !( uintptr_t(pred) & FLAG ), "use of corrupted pointer!" );
191#if TBB_USE_ASSERT
192 __TBB_control_consistency_helper(); // on "m.q_tail"
193 __TBB_ASSERT( !__TBB_load_relaxed(pred->my_next), "the predecessor has another successor!");
194#endif
195 __TBB_store_with_release(pred->my_next,this);
196 if( pred_state != STATE_ACTIVEREADER ) {
197#if DO_ITT_NOTIFY
198 sync_prepare_done = true;
199 ITT_NOTIFY(sync_prepare, my_mutex);
200#endif
201 spin_wait_until_eq(my_going, 1);

Callers

nothing calls this directly

Calls 7

__TBB_store_relaxedFunction · 0.85
__TBB_load_relaxedFunction · 0.85
__TBB_store_with_releaseFunction · 0.85
spin_wait_until_eqFunction · 0.85
spin_wait_while_eqFunction · 0.85
__TBB_load_with_acquireFunction · 0.85
state_tEnum · 0.70

Tested by

no test coverage detected