Open
Conversation
Use higher half of AtomicUsize to track mutable borrows, instead of just the highest bit. This is in preparation to implement map_split() for AtomicRef and AtomicRefMut, the latter of which will require having more than one mutable borrow. Unfortunately, this means that dropping an AtomicBorrowRefMut cannot unconditionally set the borrow count to zero anymore, as in the future there may be more than one mutable borrow. We need to drop the reference count by one, and also clear the lower bits for failed attempts to acquire an immutable borrow, which can only be done in a single step with a CAS loop.
Add a new method to split an AtomicRef / AtomicRefMut into two, by
borrowing from distinct parts of the backing data, just like
Ref{,Mut}::map_split() in the standard library.
Unfortunately, the mutable borrow increment during the split must be
peformed with a CAS loop, as we cannot afford to overflow the borrow
count without potentially triggering undefined behavior.
Add as well some basic tests to verify the functionality of the new
methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Implement
map_split()forAtomicRefandAtomicRefMut, equivalent toRef::map_split()andRefMut::map_split()in the standard library. This method allows splitting the reference types into 2 by borrowing different parts of the data protected by the cell.In order to do this, change the internal implementation so that mutable and immutable borrows are tracked in the higher and lower halves of the internal
AtomicUsizerespectively. Before, only the highest bit was dedicated to track a mutable borrow, and the rest was dedicated to immutable ones.NOTE: The changes I introduce here do not alter the performance of the already existing functionality, with one exception: dropping an
AtomicRefMutinvolves a CAS loop, where it used to be a single atomic swap.The reason for this change is that the atomic operation on drop needs to do 2 things: clear the current mutable borrow and all immutable borrows that failed (since these are left as benign side effects). With a single mutable borrow, this was done by simply setting the variable to zero. With several mutable borrows, the operation needs to decrement by 1 the higher half of the
AtomicUsize, and set to zero the lowest half. This can only be done in a single atomic step with a CAS.