Changeset 95330c33
- Timestamp:
- Oct 31, 2025, 11:49:13 AM (9 days ago)
- Branches:
- master
- Children:
- 1034059
- Parents:
- 14a51d3
- Location:
- libcfa/src/concurrency
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
r14a51d3 r95330c33 583 583 } 584 584 } 585 585 586 //----------------------------------------------------------------------------- 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 591 thread$ * 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 605 void ?{}( semaphore & sem, ssize_t count = 1 ) with( sem ) { 606 count$ = count; 607 (lock$){}; 608 (waiting$){}; 609 } 610 611 bool 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 603 617 park(); 604 return true; 618 return false; 619 } // if 620 unlock( lock$ ); 621 return true; 622 } 623 624 bool 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 605 630 } 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(); 607 639 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 645 bool 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 656 bool V( semaphore & sem ) with( sem ) { 612 657 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); 630 666 return thrd != 0p; 631 667 } 632 668 633 bool V( semaphore & this, unsigned diff) with( this) {669 bool V( semaphore & sem, size_t diff ) with( sem ) { 634 670 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$ ); 644 676 return thrd != 0p; 645 677 } 646 -
libcfa/src/concurrency/locks.hfa
r14a51d3 r95330c33 11 11 // Created On : Thu Jan 21 19:46:50 2021 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Thu Aug 21 22:36:44202514 // Update Count : 2313 // Last Modified On : Fri Oct 31 09:20:22 2025 14 // Update Count : 59 15 15 // 16 16 … … 81 81 82 82 83 84 // -----------------------------------------------------------------------------85 // Semaphore 83 //----------------------------------------------------------------------------- 84 // Semaphore, counting 85 86 86 struct 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 97 void ?{}( 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. 100 bool P( semaphore & sem ); 101 static inline bool P( semaphore & sem, uintptr_t shadow ) { active_thread()->shadow$ = shadow; return P( sem ); } 102 bool P( semaphore & sem, semaphore & lock ); // atomic block and release 103 bool try_P( semaphore & sem ); 104 static inline bool P( semaphore & sem, semaphore & lock, uintptr_t shadow ) { active_thread()->shadow$ = shadow; return P( sem, lock ); } 105 bool V( semaphore & sem ); 106 bool V( semaphore & sem, size_t count ); 107 static 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 } 116 static 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 118 static inline bool empty( semaphore & sem ) with( sem ) { return count$ == 0; } // empty waiting queue 119 98 120 99 121 //----------
Note:
See TracChangeset
for help on using the changeset viewer.