Changeset eb5962a for libcfa/src/concurrency/kernel
- Timestamp:
- Jun 21, 2022, 1:39:24 PM (4 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- b62d1d6
- Parents:
- 1df492a (diff), 1dbbef6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
libcfa/src/concurrency/kernel/fwd.hfa (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel/fwd.hfa
r1df492a reb5962a 200 200 struct thread$ * expected = this.ptr; 201 201 if(expected == 1p) return false; 202 /* paranoid */ verify( expected == 0p );203 202 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 204 203 park(); … … 213 212 thread$ * post(oneshot & this, bool do_unpark = true) { 214 213 struct thread$ * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST); 215 if( got == 0p ) return 0p;214 if( got == 0p || got == 1p ) return 0p; 216 215 if(do_unpark) unpark( got ); 217 216 return got; … … 263 262 264 263 // The future is not fulfilled, try to setup the wait context 265 /* paranoid */ verify( expected == 0p );266 264 if(__atomic_compare_exchange_n(&this.ptr, &expected, &wait_ctx, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 267 265 return true; … … 275 273 // should retract the wait ctx 276 274 // intented to be use by wait, wait_any, waitfor, etc. rather than used directly 277 void retract( future_t & this, oneshot & wait_ctx ) { 278 // Remove the wait context 279 struct oneshot * got = __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST); 280 281 // got == 0p: future was never actually setup, just return 282 if( got == 0p ) return; 283 284 // got == wait_ctx: since fulfil does an atomic_swap, 285 // if we got back the original then no one else saw context 286 // It is safe to delete (which could happen after the return) 287 if( got == &wait_ctx ) return; 288 289 // got == 1p: the future is ready and the context was fully consumed 290 // the server won't use the pointer again 291 // It is safe to delete (which could happen after the return) 292 if( got == 1p ) return; 293 294 // got == 2p: the future is ready but the context hasn't fully been consumed 295 // spin until it is safe to move on 296 if( got == 2p ) { 297 while( this.ptr != 1p ) Pause(); 298 return; 299 } 300 301 // got == any thing else, something wen't wrong here, abort 302 abort("Future in unexpected state"); 275 bool retract( future_t & this, oneshot & wait_ctx ) { 276 for() { 277 struct oneshot * expected = this.ptr; 278 279 // expected == 0p: future was never actually setup, just return 280 if( expected == 0p ) return false; 281 282 // expected == 1p: the future is ready and the context was fully consumed 283 // the server won't use the pointer again 284 // It is safe to delete (which could happen after the return) 285 if( expected == 1p ) return true; 286 287 // expected == 2p: the future is ready but the context hasn't fully been consumed 288 // spin until it is safe to move on 289 if( expected == 2p ) { 290 while( this.ptr != 1p ) Pause(); 291 /* paranoid */ verify( this.ptr == 1p ); 292 return true; 293 } 294 295 // expected != wait_ctx: the future was setup with a different context ?!?! 296 // something went wrong here, abort 297 if( expected != &wait_ctx ) abort("Future in unexpected state"); 298 299 // we still have the original context, then no one else saw it 300 // attempt to remove the context so it doesn't get consumed. 301 if(__atomic_compare_exchange_n( &this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 302 return false; 303 } 304 } 303 305 } 304 306 … … 379 381 return ret; 380 382 } 383 384 // Wait for any future to be fulfilled 385 forall(T& | sized(T) | { bool setup( T&, oneshot & ); bool retract( T&, oneshot & ); }) 386 T & wait_any( T * futures, size_t num_futures ) { 387 oneshot temp; 388 389 // setup all futures 390 // if any are already satisfied return 391 for ( i; num_futures ) { 392 if( !setup(futures[i], temp) ) return futures[i]; 393 } 394 395 // Wait context is setup, just wait on it 396 wait( temp ); 397 398 size_t ret; 399 // attempt to retract all futures 400 for ( i; num_futures ) { 401 if ( retract( futures[i], temp ) ) ret = i; 402 } 403 404 return futures[ret]; 405 } 381 406 } 382 407
Note:
See TracChangeset
for help on using the changeset viewer.