Make AtomTable fully safe and prepare for garbage collection #2736
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.
This is a followup to #2727 that gives
AtomTable
the ability to verify thatAtom
s are safe to dereference and the ability to shuffle their layout for garbage collection purposes, by adding another layer of indirection.Prior to this change,
Atom
s would contain the offset of theirAtomHeader
within a buffer. This lets us resize the buffer to add new atoms, but it is prone to issues caused by atoms with invalid offsets and it doesn't let us defragment theAtomTable
once garbage collection is introduced.With this change, the
Atom
s now store an index into an array of indices, meaning that verifying the validity of an atom is as simple as checking that it is within this array:This also lets us safely change the order of atoms within the buffer, by changing the offsets, without needing to modify the existing
Atom
s, which paves the way towards garbage collection withinAtomTable
.One important detail with my implementation is that the
offsets
array is stored within anArcu
, which means that the read from the buffer inAtom::as_ptr
now depends onatom_table.inner.offsets.read()
, which is an acquire atomic operation. When a new atom is added to the table withAtomTable::build_with
, the write to the buffer is sequenced beforeatom_table.inner.offsets.replace(new_offsets)
:Atom::as_ptr
is now guaranteed (by my limited experience with atomics) to observe the changes as expected.Instances where the lack of this property cause actual issues are exceedingly rare. A thread would need to somehow have access to an atom offset created from another thread, without synchronization, and immediately try to read its data.
The
Sync
-ness ofAtomTable
is now proved, making it (hopefully) safe :)Please don't be scared by the number of commits and the number of lines changed, they will reduce once #2727 gets merged.