Expand description
An attempt at Rcu with grace periods
We can allocate Rcu
just like you would a Arc
.
let v = rcu_clean::graceful::Rcu::new("hello");
These pointers are freed just like an ordinary Arc
. The big difference is
that you can update these pointers while they are being read, but reading
from the pointers requires a Grace
.
let v = rcu_clean::graceful::Rcu::new(vec![1,2,3,4]);
{
let grace = rcu_clean::graceful::Grace::new();
let read = v.read(&grace);
let mut iter = read.iter();
// Demonstrate that we can start iterating through our vec.
assert_eq!(Some(&1), iter.next());
// Now let's modify the vec.
v.update(|v| v.push(5));
assert_eq!(4, read.len()); // `read` still refers to the 4-element vec.
assert_eq!(Some(&2), iter.next()); // the iterator is still working.
assert_eq!(5, v.read(&grace).len()); // a new read gets the updated value
}
// At this point the 4-element vec will be freed, since the grace period is over.
The fanciness of this approach is that while the Grace
costs something to
create and drop, the [ReadGuard
] created by v.read()
costs nothing
either to create or to drop, so reads are literally free (on strongly
ordered machines) once you enter a grace period. Technically the reads cost
a AtomicPtr::load(Ordering::Acquire)
, which might be more expensive than a
pointer read, but should not be much so, and should be far cheaper than a
RwLock::read
which would be the std
alternative for a data structure
with many readers and few writers.