urcu/collections/hashmap/
reference.rs

1use std::marker::PhantomData;
2use std::ptr::NonNull;
3
4use crate::collections::hashmap::raw::RawNode;
5use crate::rcu::flavor::RcuFlavor;
6use crate::RcuRef;
7
8/// An owned RCU reference to a element removed from an [`RcuHashMap`].
9///
10/// [`RcuHashMap`]: crate::collections::hashmap::container::RcuHashMap
11pub struct RefOwned<K, V>(Box<RawNode<K, V>>);
12
13impl<K, V> RefOwned<K, V> {
14    /// Returns the key of the entry.
15    pub fn key(&self) -> &K {
16        &self.0.key
17    }
18
19    /// Returns the value of the entry.
20    pub fn value(&self) -> &V {
21        &self.0.value
22    }
23}
24
25/// #### Safety
26///
27/// It is safe to send to another thread if the underlying `K` and `V` are `Send`.
28unsafe impl<K: Send, V: Send> Send for RefOwned<K, V> {}
29
30/// #### Safety
31///
32/// It is safe to have references from multiple threads if the underlying `K` and `V` are `Sync`.
33unsafe impl<K: Sync, V: Sync> Sync for RefOwned<K, V> {}
34
35/// An owned RCU reference to a element removed from an [`RcuHashMap`].
36///
37/// [`RcuHashMap`]: crate::collections::hashmap::container::RcuHashMap
38pub struct Ref<K, V, F>
39where
40    K: Send + 'static,
41    V: Send + 'static,
42    F: RcuFlavor + 'static,
43{
44    ptr: *mut RawNode<K, V>,
45    _context: PhantomData<*const F>,
46}
47
48impl<K, V, F> Ref<K, V, F>
49where
50    K: Send,
51    V: Send,
52    F: RcuFlavor,
53{
54    pub(crate) fn new(ptr: NonNull<RawNode<K, V>>) -> Self {
55        Self {
56            ptr: ptr.as_ptr(),
57            _context: PhantomData,
58        }
59    }
60
61    pub fn key(&self) -> &K {
62        // SAFETY: The pointer is never null.
63        &unsafe { self.ptr.as_ref_unchecked() }.key
64    }
65
66    pub fn value(&self) -> &V {
67        // SAFETY: The pointer is never null.
68        &unsafe { self.ptr.as_ref_unchecked() }.value
69    }
70}
71
72impl<K, V, F> Drop for Ref<K, V, F>
73where
74    K: Send + 'static,
75    V: Send + 'static,
76    F: RcuFlavor + 'static,
77{
78    fn drop(&mut self) {
79        if !self.ptr.is_null() {
80            Self {
81                ptr: self.ptr,
82                _context: Default::default(),
83            }
84            .safe_cleanup();
85        }
86    }
87}
88
89/// #### Safety
90///
91/// The memory reclamation upon dropping is properly deferred after the RCU grace period.
92unsafe impl<K, V, F> RcuRef<F> for Ref<K, V, F>
93where
94    K: Send,
95    V: Send,
96    F: RcuFlavor,
97{
98    type Output = RefOwned<K, V>;
99
100    unsafe fn take_ownership_unchecked(mut self) -> Self::Output {
101        let output = RefOwned(Box::from_raw(self.ptr));
102
103        // SAFETY: We don't want deferred cleanup when dropping `self`.
104        self.ptr = std::ptr::null_mut();
105
106        output
107    }
108}
109
110unsafe impl<K, V, F> Send for Ref<K, V, F>
111where
112    K: Send,
113    V: Send,
114    F: RcuFlavor,
115{
116}