Ignore:
Timestamp:
Jun 21, 2022, 1:39:24 PM (4 years ago)
Author:
JiadaL <j82liang@…>
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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel/fwd.hfa

    r1df492a reb5962a  
    200200                                        struct thread$ * expected = this.ptr;
    201201                                        if(expected == 1p) return false;
    202                                         /* paranoid */ verify( expected == 0p );
    203202                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    204203                                                park();
     
    213212                        thread$ * post(oneshot & this, bool do_unpark = true) {
    214213                                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;
    216215                                if(do_unpark) unpark( got );
    217216                                return got;
     
    263262
    264263                                        // The future is not fulfilled, try to setup the wait context
    265                                         /* paranoid */ verify( expected == 0p );
    266264                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, &wait_ctx, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    267265                                                return true;
     
    275273                        // should retract the wait ctx
    276274                        // 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                                }
    303305                        }
    304306
     
    379381                                return ret;
    380382                        }
     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                        }
    381406                }
    382407
Note: See TracChangeset for help on using the changeset viewer.