Implement AtomicRef{,Mut}::map_split()
#33
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.