Module rcu_clean::graceful

source ·
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.

Structs

A grace period
A reference-counted RCU pointer with grace periods
A reference to contents that are being read