Changeset 1c56bf7


Ignore:
Timestamp:
Jun 10, 2022, 2:59:21 PM (6 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
master, pthread-emulation, qualifiedEnum
Children:
f3da205
Parents:
6d41f66
Message:

Fixed retract to not reset the future when retracting.

File:
1 edited

Legend:

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

    r6d41f66 r1c56bf7  
    274274                        // intented to be use by wait, wait_any, waitfor, etc. rather than used directly
    275275                        bool retract( future_t & this, oneshot & wait_ctx ) {
    276                                 // Remove the wait context
    277                                 struct oneshot * got = __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST);
    278 
    279                                 // got == 0p: future was never actually setup, just return
    280                                 if( got == 0p ) return false;
    281 
    282                                 // got == wait_ctx: since fulfil does an atomic_swap,
    283                                 // if we got back the original then no one else saw context
    284                                 // It is safe to delete (which could happen after the return)
    285                                 if( got == &wait_ctx ) return false;
    286 
    287                                 // got == 1p: the future is ready and the context was fully consumed
    288                                 // the server won't use the pointer again
    289                                 // It is safe to delete (which could happen after the return)
    290                                 if( got == 1p ) return true;
    291 
    292                                 // got == 2p: the future is ready but the context hasn't fully been consumed
    293                                 // spin until it is safe to move on
    294                                 if( got == 2p ) {
    295                                         while( this.ptr != 1p ) Pause();
    296                                         return false;
    297                                 }
    298 
    299                                 // got == any thing else, something wen't wrong here, abort
    300                                 abort("Future in unexpected state");
     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                                }
    301305                        }
    302306
Note: See TracChangeset for help on using the changeset viewer.