pub struct RcuCell<T> { /* private fields */ }Expand description
A concurrent data structure that allows for safe, read-copy-update (RCU) style access to its value.
§Grace period serialization
Only one old value can be pending reclamation at a time (single
ptr_counter_to_clear slot). If multiple writers call write
concurrently while readers hold guards to old values, their grace periods
are serialized. This is acceptable for read-heavy workloads but can cause
writer stalls under heavy write contention with long-lived readers.
Implementations§
Source§impl<T> RcuCell<T>
impl<T> RcuCell<T>
Sourcepub fn new(value: T) -> Self
pub fn new(value: T) -> Self
Creates a new RcuCell with the given initial value.
§Example
let rcu_cell = rcu_128::RcuCell::new(42);Examples found in repository?
5fn main() {
6 let x = rcu_128::RcuCell::new(0);
7 std::thread::scope(|s| {
8 s.spawn(|| {
9 for i in 0..40 {
10 let t = Instant::now();
11 if i < 20 {
12 x.write(i);
13 } else {
14 x.update(|v| v + 1);
15 }
16 println!("Update {i} used time: {:?}", t.elapsed());
17 sleep((t + Duration::from_millis(100)).duration_since(Instant::now()));
18 }
19 });
20 s.spawn(|| {
21 // Always has 4 guards alive
22 let mut guards = [x.read(), x.read(), x.read(), x.read()];
23 for idx in 0..400 {
24 let r = x.read();
25 println!("Read value: {}", *r);
26 guards[idx % 4] = r;
27 sleep(Duration::from_millis(10));
28 }
29 });
30 })
31}Sourcepub fn read(&self) -> RcuGuard<'_, T>
pub fn read(&self) -> RcuGuard<'_, T>
Provides read access to the value stored in the RcuCell.
This function returns an RcuGuard, which allows for safe,
concurrent read access to the RcuCell’s value.
Once all RcuGuard instances referencing a particular value are
dropped, the value can be safely released during an update or write.
§Example
let rcu_cell = rcu_128::RcuCell::new(42);
{
let guard = rcu_cell.read();
assert_eq!(*guard, 42);
}Examples found in repository?
5fn main() {
6 let x = rcu_128::RcuCell::new(0);
7 std::thread::scope(|s| {
8 s.spawn(|| {
9 for i in 0..40 {
10 let t = Instant::now();
11 if i < 20 {
12 x.write(i);
13 } else {
14 x.update(|v| v + 1);
15 }
16 println!("Update {i} used time: {:?}", t.elapsed());
17 sleep((t + Duration::from_millis(100)).duration_since(Instant::now()));
18 }
19 });
20 s.spawn(|| {
21 // Always has 4 guards alive
22 let mut guards = [x.read(), x.read(), x.read(), x.read()];
23 for idx in 0..400 {
24 let r = x.read();
25 println!("Read value: {}", *r);
26 guards[idx % 4] = r;
27 sleep(Duration::from_millis(10));
28 }
29 });
30 })
31}Sourcepub fn write(&self, value: T)
pub fn write(&self, value: T)
Writes a new value into the RcuCell.
The new value becomes immediately visible to subsequent readers. This method blocks until all readers of the old value have dropped their guards, then frees the old value.
Multiple concurrent write calls are allowed (last-writer-wins).
Use update if you need read-modify-write semantics.
§Example
let rcu_cell = rcu_128::RcuCell::new(42);
rcu_cell.write(100);
{
let guard = rcu_cell.read();
assert_eq!(*guard, 100);
}Examples found in repository?
5fn main() {
6 let x = rcu_128::RcuCell::new(0);
7 std::thread::scope(|s| {
8 s.spawn(|| {
9 for i in 0..40 {
10 let t = Instant::now();
11 if i < 20 {
12 x.write(i);
13 } else {
14 x.update(|v| v + 1);
15 }
16 println!("Update {i} used time: {:?}", t.elapsed());
17 sleep((t + Duration::from_millis(100)).duration_since(Instant::now()));
18 }
19 });
20 s.spawn(|| {
21 // Always has 4 guards alive
22 let mut guards = [x.read(), x.read(), x.read(), x.read()];
23 for idx in 0..400 {
24 let r = x.read();
25 println!("Read value: {}", *r);
26 guards[idx % 4] = r;
27 sleep(Duration::from_millis(10));
28 }
29 });
30 })
31}Sourcepub fn update(&self, f: impl FnOnce(&T) -> T)
pub fn update(&self, f: impl FnOnce(&T) -> T)
Updates the value stored in the RcuCell using a provided function.
This function applies the given closure f to the current value,
replacing it with the returned value. The closure runs under an
exclusive lock, so concurrent update and write calls are
serialized — the closure is guaranteed to run exactly once.
§Example
let rcu_cell = rcu_128::RcuCell::new(42);
rcu_cell.update(|&old_value| old_value + 1);
{
let guard = rcu_cell.read();
assert_eq!(*guard, 43);
}Examples found in repository?
5fn main() {
6 let x = rcu_128::RcuCell::new(0);
7 std::thread::scope(|s| {
8 s.spawn(|| {
9 for i in 0..40 {
10 let t = Instant::now();
11 if i < 20 {
12 x.write(i);
13 } else {
14 x.update(|v| v + 1);
15 }
16 println!("Update {i} used time: {:?}", t.elapsed());
17 sleep((t + Duration::from_millis(100)).duration_since(Instant::now()));
18 }
19 });
20 s.spawn(|| {
21 // Always has 4 guards alive
22 let mut guards = [x.read(), x.read(), x.read(), x.read()];
23 for idx in 0..400 {
24 let r = x.read();
25 println!("Read value: {}", *r);
26 guards[idx % 4] = r;
27 sleep(Duration::from_millis(10));
28 }
29 });
30 })
31}