add intrusive atomic ref count (CRTP)#5
Open
AneesPatel wants to merge 1 commit into
Open
Conversation
Inline refcount in the object, no separate control block allocation. Explains the acq_rel ordering on release() — easy to get wrong and hard to debug if you use relaxed there. Good building block for reference-counted lock-free nodes.
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.
What
Intrusive atomic reference count using CRTP. The building block behind
shared_ptr's control block and reference-counted lock-free nodes.Why intrusive vs shared_ptr
shared_ptrstores its reference count in a separate heap-allocated control block - two allocations and two pointer dereferences per access. An intrusive ref count lives inline in the object itself, so one allocation and one pointer. Matters when you're building chains of lock-free nodes.The memory ordering story
add_refusesmemory_order_relaxed- fine because the caller must have already obtained a valid pointer through some synchronized path, so the happens-before is already established.releaseusesmemory_order_acq_rel- the release ensures our writes are flushed before we touch the count, the acquire ensures we see all previous releases before we call delete. Without acq_rel on the last decrement you can delete an object while another thread's writes to it are still in flight. This is a genuinely easy mistake to make.Files
include/AtomicRefCount.htests/test_atomicrefcount.cpp- 8 threads all hold+release the same object, verify destructor called exactly onceCMakeLists.txt