Changeset 00aa122 for libcfa/src/concurrency/future.hfa
- Timestamp:
- Nov 24, 2025, 4:13:37 PM (20 hours ago)
- Branches:
- master
- Parents:
- fbaea970
- File:
-
- 1 edited
-
libcfa/src/concurrency/future.hfa (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/future.hfa
rfbaea970 r00aa122 10 10 // Created On : Wed Jan 06 17:33:18 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Nov 23 22:48:08202513 // Update Count : 2 0812 // Last Modified On : Mon Nov 24 16:08:52 2025 13 // Update Count : 222 14 14 // 15 15 … … 100 100 except = 0p; 101 101 state = FUTURE_EMPTY$; 102 lock{};103 102 } 104 103 … … 320 319 321 320 //-------------------------------------------------------------------------------------------------------- 322 // These futures below do not support waituntil statements so they may not have as many features as 'future' 323 // however the 'single_future' is cheap and cheerful and is most likely more performant than 'future' 324 // since it uses raw atomics and no locks 325 // 326 // As far as 'multi_future' goes I can't see many use cases as it will be less performant than 'future' 327 // since it is monitor based and also is not compatible with waituntil statement. 321 // This future does not support waituntil statements so it does not have as many features as 'future'. 322 // However, it is cheap and cheerful and is more performant than 'future' since it uses raw atomics 323 // and no locks 328 324 //-------------------------------------------------------------------------------------------------------- 329 325 330 326 forall( T ) { 327 // PUBLIC 328 331 329 struct single_future { 332 330 inline future_t; … … 335 333 336 334 static inline { 337 // Reset future back to original state 338 void reset(single_future(T) & this) { reset( (future_t&)this ); } 339 340 // check if the future is available 341 bool available( single_future(T) & this ) { return available( (future_t&)this ); } 342 343 // Mark the future as abandoned, meaning it will be deleted by the server 344 // This doesn't work beause of the potential need for a destructor 345 // void abandon( single_future(T) & this ); 346 347 // Fulfil the future, returns whether or not someone was unblocked 348 thread$ * fulfil( single_future(T) & this, T result ) { 349 this.result = result; 350 return fulfil( (future_t&)this ); 351 } 352 353 // Wait for the future to be fulfilled 354 // Also return whether the thread had to block or not 355 [T, bool] wait( single_future(T) & this ) { 356 bool r = wait( (future_t&)this ); 357 return [this.result, r]; 358 } 359 360 // Wait for the future to be fulfilled 361 T wait( single_future(T) & this ) { 362 [T, bool] tt; 363 tt = wait( this ); 364 return tt.0; 365 } 366 } 367 } 368 369 forall( T ) { 370 monitor multi_future { 371 inline future_t; 372 condition blocked; 373 bool has_first; 374 T result; 375 }; 376 377 static inline { 378 void ?{}(multi_future(T) & this) { 379 this.has_first = false; 380 } 381 382 bool $first( multi_future(T) & mutex this ) { 383 if ( this.has_first ) { 384 wait( this.blocked ); 385 return false; 386 } 387 388 this.has_first = true; 389 return true; 390 } 391 392 void $first_done( multi_future(T) & mutex this ) { 393 this.has_first = false; 394 signal_all( this.blocked ); 395 } 396 397 // Reset future back to original state 398 void reset(multi_future(T) & mutex this) { 399 if ( this.has_first != false ) abort("Attempting to reset a multi_future with at least one blocked threads"); 400 if ( ! empty( this.blocked ) ) abort("Attempting to reset a multi_future with multiple blocked threads"); 401 reset( (future_t&)*(future_t*)((uintptr_t)&this + sizeof(monitor$)) ); 402 } 403 404 // Fulfil the future, returns whether or not someone was unblocked 405 bool fulfil( multi_future(T) & this, T result ) { 406 this.result = result; 407 return fulfil( (future_t&)*(future_t*)((uintptr_t)&this + sizeof(monitor$)) ) != 0p; 408 } 409 410 // Wait for the future to be fulfilled 411 // Also return whether the thread had to block or not 412 [T, bool] wait( multi_future(T) & this ) { 413 bool sw = $first( this ); 414 bool w = !sw; 415 if ( sw ) { 416 w = wait( (future_t&)*(future_t*)((uintptr_t)&this + sizeof(monitor$)) ); 417 $first_done( this ); 418 } 419 420 return [this.result, w]; 421 } 422 423 // Wait for the future to be fulfilled 424 T wait( multi_future(T) & this ) { 425 return wait( this ).0; 426 } 427 } 428 } 335 // PUBLIC 336 337 bool available( single_future(T) & fut ) { return available( (future_t &)fut ); } // future result available ? 338 339 // Return a value/exception from the future. 340 [T, bool] get( single_future(T) & fut ) { return [fut.result, wait( fut )]; } 341 T get( single_future(T) & fut ) { wait( fut ); return fut.result; } 342 T ?()( single_future(T) & fut ) { return get( fut ); } // alternate interface 343 344 // Load a value into the future, returns whether or not waiting threads. 345 bool fulfil( single_future(T) & fut, T result ) { 346 fut.result = result; 347 return fulfil( (future_t &)fut ) != 0p; 348 } 349 bool ?()( single_future(T) & fut, T val ) { return fulfil( fut, val ); } // alternate interface 350 351 void reset( single_future(T) & fut ) { reset( (future_t &)fut ); } // mark future as empty (for reuse) 352 } // static inline 353 } // forall( T )
Note:
See TracChangeset
for help on using the changeset viewer.