You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now assume two threads are waiting on acquire call:
T1: { s.acquire(); }
T2: { s.acquire(); }
And third thread calls release, to release two times by one:
T3: { s.release(1); s.release(1); }
first release call unblocks one waiting thread. Assume it is T1, and assume that before T1 did compare_exchange_strong, T3 executes the second release call. Since second release observes __a to be 1 (from the previous call), it never releases T2. So T2 stays blocked while __a == 1.
If this analysis is correct, I would have called notify_all() for all cases if __a was observed to be 0. Except for counting_semaphore<1> specialization, where it is always safe to call notify_one().
Another alternative could be avoiding 0 < __a.fetch_add check, this will unblock T2 in subsequent release in my example, but it looks like to be less efficient and more complex.
The text was updated successfully, but these errors were encountered:
Extended Description
counting_semaphore::release only notifies waiting thread when count reaches zero. it only notifies one waiting thread if __update == 1:
llvm-project/libcxx/include/semaphore
Lines 86 to 94 in 4357986
counting_semaphore::acquire enters waiting when __a is observed to be zero:
llvm-project/libcxx/include/semaphore
Lines 96 to 103 in 4357986
Now assume two threads are waiting on acquire call:
T1: { s.acquire(); }
T2: { s.acquire(); }
And third thread calls release, to release two times by one:
T3: { s.release(1); s.release(1); }
first release call unblocks one waiting thread. Assume it is T1, and assume that before T1 did compare_exchange_strong, T3 executes the second release call. Since second release observes __a to be 1 (from the previous call), it never releases T2. So T2 stays blocked while __a == 1.
If this analysis is correct, I would have called notify_all() for all cases if __a was observed to be 0. Except for counting_semaphore<1> specialization, where it is always safe to call notify_one().
Another alternative could be avoiding 0 < __a.fetch_add check, this will unblock T2 in subsequent release in my example, but it looks like to be less efficient and more complex.
The text was updated successfully, but these errors were encountered: