idr_ebr/
handles.rs

1use std::{fmt, mem, ops::Deref};
2
3use crate::{
4    EbrGuard,
5    config::Config,
6    key::Key,
7    page::{self, Page},
8    slot::Slot,
9};
10
11// === VacantEntry ===
12
13/// A handle to a vacant entry in an IDR.
14///
15/// It allows constructing values with the key that they will be assigned to.
16///
17/// See [`Idr::vacant_entry()`] for more details.
18///
19/// [`Idr::vacant_entry()`]: crate::Idr::vacant_entry
20#[must_use]
21pub struct VacantEntry<'s, T: 'static, C: Config> {
22    page: &'s Page<T, C>,
23    slot: &'s Slot<T, C>,
24    key: Key,
25}
26
27impl<'s, T: 'static, C: Config> VacantEntry<'s, T, C> {
28    pub(crate) fn new(page: &'s Page<T, C>, slot: &'s Slot<T, C>, key: Key) -> Self {
29        Self { page, slot, key }
30    }
31
32    /// Returns the key at which this entry will be inserted.
33    ///
34    /// An entry stored in this entry will be associated with this key.
35    #[must_use]
36    #[inline]
37    pub fn key(&self) -> Key {
38        self.key
39    }
40
41    /// Inserts a value in the IDR.
42    ///
43    /// This method is wait-free.
44    ///
45    /// To get the key at which this value will be inserted, use
46    /// [`VacantEntry::key()`] prior to calling this method.
47    #[inline]
48    pub fn insert(self, value: T) {
49        self.slot.init(value);
50        mem::forget(self);
51    }
52}
53
54impl<T: 'static, C: Config> Drop for VacantEntry<'_, T, C> {
55    #[inline]
56    fn drop(&mut self) {
57        // SAFETY: The slot belongs to this page by construction.
58        unsafe { self.page.add_free(self.slot) };
59    }
60}
61
62impl<T, C: Config> fmt::Debug for VacantEntry<'_, T, C> {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        f.debug_struct("VacantEntry")
65            .field("key", &self.key)
66            .finish_non_exhaustive()
67    }
68}
69
70// === BorrowedEntry ===
71
72/// A borrowed handle that allows access to an occupied entry in an IDR.
73///
74/// See [`Idr::get()`] for more details.
75///
76/// [`Idr::get()`]: crate::Idr::get
77#[must_use]
78pub struct BorrowedEntry<'g, T>(sdd::Ptr<'g, T> /* non-null */);
79
80impl<'g, T> BorrowedEntry<'g, T> {
81    pub(crate) fn new(ptr: sdd::Ptr<'g, T>) -> Option<Self> {
82        (!ptr.is_null()).then_some(Self(ptr))
83    }
84
85    /// Creates an owned handle to the entry.
86    ///
87    /// It returns `None` if the entry has been removed from the IDR and
88    /// no owned handles exist.
89    ///
90    /// This method is lock-free, but it modifies the memory by incrementing the
91    /// reference counter.
92    ///
93    /// See [`OwnedEntry`] for more details.
94    #[inline]
95    pub fn to_owned(self) -> Option<OwnedEntry<T>> {
96        self.0.get_shared().map(OwnedEntry)
97    }
98}
99
100impl<T> Copy for BorrowedEntry<'_, T> {}
101
102impl<T> Clone for BorrowedEntry<'_, T> {
103    #[inline]
104    fn clone(&self) -> Self {
105        *self
106    }
107}
108
109impl<T> Deref for BorrowedEntry<'_, T> {
110    type Target = T;
111
112    #[inline]
113    fn deref(&self) -> &Self::Target {
114        let maybe_ref = self.0.as_ref();
115
116        // SAFETY: The pointer is non-null, checked in `new()`.
117        unsafe { maybe_ref.unwrap_unchecked() }
118    }
119}
120
121impl<T: fmt::Debug> fmt::Debug for BorrowedEntry<'_, T> {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        fmt::Debug::fmt(&**self, f)
124    }
125}
126
127impl<T: PartialEq<T>> PartialEq<T> for BorrowedEntry<'_, T> {
128    #[inline]
129    fn eq(&self, other: &T) -> bool {
130        (**self).eq(other)
131    }
132}
133
134// === OwnedEntry ===
135
136/// An owned handle that allows access to an occupied entry in an IDR.
137///
138/// See [`Idr::get_owned()`] for more details.
139///
140/// [`Idr::get_owned()`]: crate::Idr::get_owned
141#[must_use]
142pub struct OwnedEntry<T>(sdd::Shared<T>);
143
144impl<T> Clone for OwnedEntry<T> {
145    #[inline]
146    fn clone(&self) -> Self {
147        Self(self.0.clone())
148    }
149}
150
151impl<T> Deref for OwnedEntry<T> {
152    type Target = T;
153
154    #[inline]
155    fn deref(&self) -> &Self::Target {
156        &self.0
157    }
158}
159
160impl<T: fmt::Debug> fmt::Debug for OwnedEntry<T> {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        fmt::Debug::fmt(&*self.0, f)
163    }
164}
165
166impl<T: PartialEq<T>> PartialEq<T> for OwnedEntry<T> {
167    #[inline]
168    fn eq(&self, other: &T) -> bool {
169        self.0.eq(other)
170    }
171}
172
173// === Iter ===
174
175/// A fused iterator over all occupied entries in the IDR.
176///
177/// See [`Idr::iter()`] for more details.
178///
179/// [`Idr::iter()`]: crate::Idr::iter
180#[must_use]
181pub struct Iter<'g, 's, T, C> {
182    pages: &'s [Page<T, C>],
183    slots: Option<page::Iter<'g, 's, T, C>>,
184    guard: &'g EbrGuard,
185}
186
187impl<'g, 's, T: 'static, C: Config> Iter<'g, 's, T, C> {
188    pub(crate) fn new(pages: &'s [Page<T, C>], guard: &'g EbrGuard) -> Self {
189        let (first, rest) = pages.split_first().expect("invalid MAX_PAGES");
190
191        Self {
192            pages: rest,
193            slots: first.iter(guard),
194            guard,
195        }
196    }
197}
198
199impl<'g, T: 'static, C: Config> Iterator for Iter<'g, '_, T, C> {
200    type Item = (Key, BorrowedEntry<'g, T>);
201
202    fn next(&mut self) -> Option<Self::Item> {
203        loop {
204            let slots = self.slots.as_mut()?;
205
206            if let Some(pair) = slots.next() {
207                return Some(pair);
208            }
209
210            let (slots, rest) = self
211                .pages
212                .split_first()
213                .map(|(next, rest)| (next.iter(self.guard), rest))
214                .unwrap_or_default();
215
216            self.pages = rest;
217            self.slots = slots;
218        }
219    }
220}
221
222impl<T: 'static, C: Config> std::iter::FusedIterator for Iter<'_, '_, T, C> {}
223
224impl<T, C> fmt::Debug for Iter<'_, '_, T, C> {
225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226        f.debug_struct("Iter").finish_non_exhaustive()
227    }
228}