1use crate::rcu_ptr::{RcuPtr, RcuReadGuard};
6use crate::rcu_read_scope::RcuReadScope;
7use crate::state_machine::rcu_drop;
8
9#[derive(Debug)]
15pub struct RcuCell<T: Send + Sync + 'static> {
16 ptr: RcuPtr<T>,
17}
18
19impl<T: Send + Sync + 'static> RcuCell<T> {
20 pub fn new(data: T) -> Self {
22 Self::from(Box::new(data))
23 }
24
25 pub fn read(&self) -> RcuReadGuard<T> {
30 self.ptr.get()
31 }
32
33 pub fn as_ref<'a>(&self, scope: &'a RcuReadScope) -> &'a T {
38 self.ptr.read(scope).as_ref().unwrap()
39 }
40
41 pub fn update(&self, data: T) {
46 let ptr = Box::into_raw(Box::new(data));
47 unsafe { self.replace(ptr) };
49 }
50
51 unsafe fn replace(&self, ptr: *mut T) {
57 let old_ptr = self.ptr.replace(ptr);
58 let object = unsafe { Box::from_raw(old_ptr) };
59 rcu_drop(object);
60 }
61}
62
63impl<T: Send + Sync + 'static> Drop for RcuCell<T> {
64 fn drop(&mut self) {
65 unsafe { self.replace(std::ptr::null_mut()) };
67 }
68}
69
70impl<T: Default + Send + Sync + 'static> Default for RcuCell<T> {
71 fn default() -> Self {
72 Self::new(T::default())
73 }
74}
75
76impl<T: Clone + Send + Sync + 'static> Clone for RcuCell<T> {
77 fn clone(&self) -> Self {
78 let value = self.read();
79 Self::new(value.clone())
80 }
81}
82
83impl<T: Send + Sync + 'static> From<Box<T>> for RcuCell<T> {
84 fn from(value: Box<T>) -> Self {
85 Self { ptr: RcuPtr::new(Box::into_raw(value)) }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::state_machine::rcu_synchronize;
93 use std::ops::Deref;
94
95 #[test]
96 fn test_rcu_cell() {
97 let value = RcuCell::new(42);
98 assert_eq!(value.read().deref(), &42);
99 }
100
101 #[test]
102 fn test_rcu_cell_set_deferred() {
103 let value = RcuCell::new(42);
104 value.update(43);
105 assert_eq!(value.read().deref(), &43);
106 rcu_synchronize();
107 }
108
109 #[test]
110 fn test_rcu_cell_drop() {
111 let value = RcuCell::new(42);
112 drop(value);
113 }
114}