Changeset 95330c33


Ignore:
Timestamp:
Oct 31, 2025, 11:49:13 AM (9 days ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
1034059
Parents:
14a51d3
Message:

rename private variable with trailing $, and restructure lock

Location:
libcfa/src/concurrency
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/locks.cfa

    r14a51d3 r95330c33  
    583583        }
    584584}
     585
    585586//-----------------------------------------------------------------------------
    586 // Semaphore
    587 void ?{}( semaphore & this, int count = 1 ) {
    588         (this.lock){};
    589         this.count = count;
    590         (this.waiting){};
    591 }
    592 void ^?{}(semaphore & this) {}
    593 
    594 bool P(semaphore & this) with( this ){
    595         lock( lock __cfaabi_dbg_ctx2 );
    596         count -= 1;
    597         if ( count < 0 ) {
    598                 // queue current task
    599                 append( waiting, active_thread() );
    600 
    601                 // atomically release spin lock and block
    602                 unlock( lock );
     587// Semaphore, counting
     588
     589// PRIVATE
     590
     591thread$ * V( semaphore & sem, const bool doUnpark ) with( sem ) {
     592        thread$ * thrd = 0p;
     593        lock( lock$ __cfaabi_dbg_ctx2 );
     594        count$ += 1;
     595        if ( count$ <= 0 ) {
     596                thrd = pop_head( waiting$ );                                            // remove task at head of waiting list
     597        }
     598        unlock( lock$ );
     599        if ( doUnpark ) unpark( thrd );                                         // make new owner
     600        return thrd;
     601}
     602
     603// PUBLIC
     604
     605void ?{}( semaphore & sem, ssize_t count = 1 ) with( sem ) {
     606        count$ = count;
     607        (lock$){};
     608        (waiting$){};
     609}
     610
     611bool P( semaphore & sem ) with( sem ) {
     612        lock( lock$ __cfaabi_dbg_ctx2 );
     613        count$ -= 1;
     614        if ( count$ < 0 ) {                                                                     // in use ?
     615                append( waiting$, active_thread() );                            // queue current task
     616                unlock( lock$ );                                                                        // atomically release spin lock and block
    603617                park();
    604                 return true;
     618                return false;
     619        } // if
     620        unlock( lock$ );
     621        return true;
     622}
     623
     624bool P( semaphore & sem, semaphore & lock ) with( sem ) {
     625        lock( lock$ __cfaabi_dbg_ctx2 );
     626        if ( &sem == &lock ) {                                                          // perform operation on self ?
     627                if ( count$ < 0 ) {                                                             // V my semaphore
     628                        unpark( pop_head( waiting$ ) );                         // unblock task at head of waiting list
     629                } // if
    605630        } else {
    606                 unlock( lock );
     631                V( sem );                                                                               // V other semaphore
     632                count$ -= 1;
     633        } // if
     634
     635        if ( count$ < 0 ) {                                                                     // in use ?
     636                append( waiting$, active_thread() );                    // queue current task
     637                unlock( lock$ );                                                                // atomically release spin lock and block
     638                park();
    607639                return false;
    608         }
    609 }
    610 
    611 thread$ * V (semaphore & this, const bool doUnpark ) with( this ) {
     640        } // if
     641        unlock( lock$ );
     642        return true;
     643}
     644
     645bool try_P( semaphore & sem ) with( sem ) {
     646        lock( lock$ __cfaabi_dbg_ctx2 );
     647        if ( count$ <= 0 ) {                                                            // in use ?
     648                unlock( lock$ );
     649                return false;
     650        } // if
     651        count$ -= 1;                                                                            // acquire
     652        unlock( lock$ );
     653        return true;
     654}
     655
     656bool V( semaphore & sem ) with( sem ) {
    612657        thread$ * thrd = 0p;
    613         lock( lock __cfaabi_dbg_ctx2 );
    614         count += 1;
    615         if ( count <= 0 ) {
    616                 // remove task at head of waiting list
    617                 thrd = pop_head( waiting );
    618         }
    619 
    620         unlock( lock );
    621 
    622         // make new owner
    623         if ( doUnpark ) unpark( thrd );
    624 
    625         return thrd;
    626 }
    627 
    628 bool V(semaphore & this) with( this ) {
    629         thread$ * thrd = V(this, true);
     658        lock( lock$ __cfaabi_dbg_ctx2 );
     659        count$ += 1;
     660        if ( count$ <= 0 ) {
     661                thrd = pop_head( waiting$ );                                    // remove task at head of waiting list
     662        }
     663        unlock( lock$ );
     664        if ( true ) unpark( thrd );                                             // make new owner
     665//      thread$ * thrd = V(sem, true);
    630666        return thrd != 0p;
    631667}
    632668
    633 bool V(semaphore & this, unsigned diff) with( this ) {
     669bool V( semaphore & sem, size_t diff ) with( sem ) {
    634670        thread$ * thrd = 0p;
    635         lock( lock __cfaabi_dbg_ctx2 );
    636         int release = max(-count, (int)diff);
    637         count += diff;
    638         for(release) {
    639                 unpark( pop_head( waiting ) );
    640         }
    641 
    642         unlock( lock );
    643 
     671        lock( lock$ __cfaabi_dbg_ctx2 );
     672        size_t release = max( (size_t)-count$, diff );
     673        count$ += diff;
     674        for ( release ) unpark( pop_head( waiting$ ) );
     675        unlock( lock$ );
    644676        return thrd != 0p;
    645677}
    646 
  • libcfa/src/concurrency/locks.hfa

    r14a51d3 r95330c33  
    1111// Created On       : Thu Jan 21 19:46:50 2021
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Thu Aug 21 22:36:44 2025
    14 // Update Count     : 23
     13// Last Modified On : Fri Oct 31 09:20:22 2025
     14// Update Count     : 59
    1515//
    1616
     
    8181
    8282
    83 
    84 //-----------------------------------------------------------------------------
    85 // Semaphore
     83//-----------------------------------------------------------------------------
     84// Semaphore, counting
     85
    8686struct semaphore {
    87         __spinlock_t lock;
    88         int count;
    89         __queue_t( thread$) waiting;
    90 };
    91 
    92 void ?{}( semaphore & this, int count = 1 );
    93 void ^?{}( semaphore & this );
    94 bool P( semaphore & this );
    95 bool V( semaphore & this );
    96 bool V( semaphore & this, unsigned count );
    97 thread$ * V( semaphore & this, bool );
     87        // PRIVATE
     88        ssize_t count$;                                                                          // - => # waiting threads, 0 => block, + => acquire
     89        __spinlock_t lock$;                                                                      // protect blocking-lock critical sections
     90        __queue_t( thread$ ) waiting$;                                           // waiting threads
     91};
     92
     93// PRIVATE
     94//thread$ * V( semaphore & sem, bool );
     95
     96// PUBLIC
     97void ?{}( semaphore & sem, ssize_t count = 1 );
     98// Return values are used for composition. Calling threads know if a thread is unblocked, which can be useful for
     99// debugging, performance instrumentation and other metadata tracking purposes.
     100bool P( semaphore & sem );
     101static inline bool P( semaphore & sem, uintptr_t shadow ) { active_thread()->shadow$ = shadow; return P( sem ); }
     102bool P( semaphore & sem, semaphore & lock );                    // atomic block and release
     103bool try_P( semaphore & sem );
     104static inline bool P( semaphore & sem, semaphore & lock, uintptr_t shadow ) { active_thread()->shadow$ = shadow; return P( sem, lock ); }
     105bool V( semaphore & sem );
     106bool V( semaphore & sem, size_t count );
     107static inline uintptr_t front( semaphore & sem ) with( sem ) { // return shadow information for first waiting thread
     108        #ifdef __CFA_DEBUG__
     109        if ( waiting$ ) {                                                                       // condition queue must not be empty
     110                abort( "Attempt to access user data on an empty semaphore lock.\n"
     111                           "Possible cause is not checking if the condition lock is empty before reading stored data." );
     112        } // if
     113        #endif // __CFA_DEBUG__
     114        return waiting$.head->shadow$;                                          // return condition information stored with blocked task
     115}
     116static inline ssize_t counter( semaphore & sem ) with( sem ) { return count$; } // - => # waiting threads, 0 => block, + => acquire
     117//static inline int ?!=?( semaphore & sem, zero_t ) with( sem ) { return count$ != 0; } // empty waiting queue
     118static inline bool empty( semaphore & sem ) with( sem ) { return count$ == 0; } // empty waiting queue
     119
    98120
    99121//----------
Note: See TracChangeset for help on using the changeset viewer.