Use acquire-release memory order for mutex::try_lock #274
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Mutex locking needs to have memory-order acquire semantics. Imagine two threads incrementing a counter, protected by a mutex:
Preconditions:
owner = nullptr
X = 0
Each thread:
mutex::try_lock
successfully performsowner.compare_exchange_strong(self, memory_order_release)
. This only guarantees that any preceding reads and writes are not reordered after this one.X = X + 1
. This is not an atomic variable and therefore depends on the memory ordering ofowner
to synchronize reads and writes.mutex::unlock
callsowner.store(nullptr)
which hasseq
ordering. This guarantees no preceding or subsequent reads or writes will be reordered.But because the CAS uses
release
memory ordering, other threads can reorder 2 before 1 and 3.This ordering is therefore possible:
X=X+1
, X=1X=X+1
, X=1Both threads read X as 0 and both set X to 1. The end state is that X=1, but it should be 2.
Using
acquire
semantics for thetry_lock
guarantees that 2 can only happen after 1 and before 3.