Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/sharded-slab-0.1.7/src/page/slot.rs
Line
Count
Source (jump to first uncovered line)
1
use super::FreeList;
2
use crate::sync::{
3
    atomic::{AtomicUsize, Ordering},
4
    hint, UnsafeCell,
5
};
6
use crate::{cfg, clear::Clear, Pack, Tid};
7
use std::{fmt, marker::PhantomData, mem, ptr, thread};
8
9
pub(crate) struct Slot<T, C> {
10
    lifecycle: AtomicUsize,
11
    /// The offset of the next item on the free list.
12
    next: UnsafeCell<usize>,
13
    /// The data stored in the slot.
14
    item: UnsafeCell<T>,
15
    _cfg: PhantomData<fn(C)>,
16
}
17
18
#[derive(Debug)]
19
pub(crate) struct Guard<T, C: cfg::Config = cfg::DefaultConfig> {
20
    slot: ptr::NonNull<Slot<T, C>>,
21
}
22
23
#[derive(Debug)]
24
pub(crate) struct InitGuard<T, C: cfg::Config = cfg::DefaultConfig> {
25
    slot: ptr::NonNull<Slot<T, C>>,
26
    curr_lifecycle: usize,
27
    released: bool,
28
}
29
30
#[repr(transparent)]
31
pub(crate) struct Generation<C = cfg::DefaultConfig> {
32
    value: usize,
33
    _cfg: PhantomData<fn(C)>,
34
}
35
36
#[repr(transparent)]
37
pub(crate) struct RefCount<C = cfg::DefaultConfig> {
38
    value: usize,
39
    _cfg: PhantomData<fn(C)>,
40
}
41
42
pub(crate) struct Lifecycle<C> {
43
    state: State,
44
    _cfg: PhantomData<fn(C)>,
45
}
46
struct LifecycleGen<C>(Generation<C>);
47
48
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
49
#[repr(usize)]
50
enum State {
51
    Present = 0b00,
52
    Marked = 0b01,
53
    Removing = 0b11,
54
}
55
56
impl<C: cfg::Config> Pack<C> for Generation<C> {
57
    /// Use all the remaining bits in the word for the generation counter, minus
58
    /// any bits reserved by the user.
59
    const LEN: usize = (cfg::WIDTH - C::RESERVED_BITS) - Self::SHIFT;
60
61
    type Prev = Tid<C>;
62
63
    #[inline(always)]
64
0
    fn from_usize(u: usize) -> Self {
65
0
        debug_assert!(u <= Self::BITS);
66
0
        Self::new(u)
67
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation<_> as sharded_slab::Pack<_>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
68
69
    #[inline(always)]
70
0
    fn as_usize(&self) -> usize {
71
0
        self.value
72
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation<_> as sharded_slab::Pack<_>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
73
}
74
75
impl<C: cfg::Config> Generation<C> {
76
0
    fn new(value: usize) -> Self {
77
0
        Self {
78
0
            value,
79
0
            _cfg: PhantomData,
80
0
        }
81
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation<_>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::new
82
}
83
84
// Slot methods which should work across all trait bounds
85
impl<T, C> Slot<T, C>
86
where
87
    C: cfg::Config,
88
{
89
    #[inline(always)]
90
0
    pub(super) fn next(&self) -> usize {
91
0
        self.next.with(|next| unsafe { *next })
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next::{closure#0}
92
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::next
93
94
    #[inline(always)]
95
0
    pub(crate) fn value(&self) -> &T {
96
0
        self.item.with(|item| unsafe { &*item })
97
0
    }
98
99
    #[inline(always)]
100
0
    pub(super) fn set_next(&self, next: usize) {
101
0
        self.next.with_mut(|n| unsafe {
102
0
            (*n) = next;
103
0
        })
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next::{closure#0}
104
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::set_next
105
106
    #[inline(always)]
107
0
    pub(crate) fn get(&self, gen: Generation<C>) -> Option<Guard<T, C>> {
108
0
        let mut lifecycle = self.lifecycle.load(Ordering::Acquire);
109
        loop {
110
            // Unpack the current state.
111
0
            let state = Lifecycle::<C>::from_packed(lifecycle);
112
0
            let current_gen = LifecycleGen::<C>::from_packed(lifecycle).0;
113
0
            let refs = RefCount::<C>::from_packed(lifecycle);
114
0
115
0
            test_println!(
116
0
                "-> get {:?}; current_gen={:?}; lifecycle={:#x}; state={:?}; refs={:?};",
117
0
                gen,
118
0
                current_gen,
119
0
                lifecycle,
120
0
                state,
121
0
                refs,
122
0
            );
123
124
            // Is it okay to access this slot? The accessed generation must be
125
            // current, and the slot must not be in the process of being
126
            // removed. If we can no longer access the slot at the given
127
            // generation, return `None`.
128
0
            if gen != current_gen || state != Lifecycle::PRESENT {
129
0
                test_println!("-> get: no longer exists!");
130
0
                return None;
131
0
            }
132
133
            // Try to increment the slot's ref count by one.
134
0
            let new_refs = refs.incr()?;
135
0
            match self.lifecycle.compare_exchange(
136
0
                lifecycle,
137
0
                new_refs.pack(lifecycle),
138
0
                Ordering::AcqRel,
139
0
                Ordering::Acquire,
140
0
            ) {
141
                Ok(_) => {
142
0
                    test_println!("-> {:?}", new_refs);
143
0
                    return Some(Guard {
144
0
                        slot: ptr::NonNull::from(self),
145
0
                    });
146
                }
147
0
                Err(actual) => {
148
0
                    // Another thread modified the slot's state before us! We
149
0
                    // need to retry with the new state.
150
0
                    //
151
0
                    // Since the new state may mean that the accessed generation
152
0
                    // is no longer valid, we'll check again on the next
153
0
                    // iteration of the loop.
154
0
                    test_println!("-> get: retrying; lifecycle={:#x};", actual);
155
0
                    lifecycle = actual;
156
                }
157
            };
158
        }
159
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::get
160
161
    /// Marks this slot to be released, returning `true` if the slot can be
162
    /// mutated *now* and `false` otherwise.
163
    ///
164
    /// This method checks if there are any references to this slot. If there _are_ valid
165
    /// references, it just marks them for modification and returns and the next thread calling
166
    /// either `clear_storage` or `remove_value` will try and modify the storage
167
0
    fn mark_release(&self, gen: Generation<C>) -> Option<bool> {
168
0
        let mut lifecycle = self.lifecycle.load(Ordering::Acquire);
169
        let mut curr_gen;
170
171
        // Try to advance the slot's state to "MARKED", which indicates that it
172
        // should be removed when it is no longer concurrently accessed.
173
        loop {
174
0
            curr_gen = LifecycleGen::from_packed(lifecycle).0;
175
0
            test_println!(
176
0
                "-> mark_release; gen={:?}; current_gen={:?};",
177
0
                gen,
178
0
                curr_gen
179
0
            );
180
181
            // Is the slot still at the generation we are trying to remove?
182
0
            if gen != curr_gen {
183
0
                return None;
184
0
            }
185
0
186
0
            let state = Lifecycle::<C>::from_packed(lifecycle).state;
187
0
            test_println!("-> mark_release; state={:?};", state);
188
0
            match state {
189
                State::Removing => {
190
0
                    test_println!("--> mark_release; cannot release (already removed!)");
191
0
                    return None;
192
                }
193
                State::Marked => {
194
0
                    test_println!("--> mark_release; already marked;");
195
0
                    break;
196
                }
197
0
                State::Present => {}
198
0
            };
199
0
200
0
            // Set the new state to `MARKED`.
201
0
            let new_lifecycle = Lifecycle::<C>::MARKED.pack(lifecycle);
202
0
            test_println!(
203
0
                "-> mark_release; old_lifecycle={:#x}; new_lifecycle={:#x};",
204
0
                lifecycle,
205
0
                new_lifecycle
206
0
            );
207
208
0
            match self.lifecycle.compare_exchange(
209
0
                lifecycle,
210
0
                new_lifecycle,
211
0
                Ordering::AcqRel,
212
0
                Ordering::Acquire,
213
0
            ) {
214
0
                Ok(_) => break,
215
0
                Err(actual) => {
216
0
                    test_println!("-> mark_release; retrying");
217
0
                    lifecycle = actual;
218
                }
219
            }
220
        }
221
222
        // Unpack the current reference count to see if we can remove the slot now.
223
0
        let refs = RefCount::<C>::from_packed(lifecycle);
224
0
        test_println!("-> mark_release: marked; refs={:?};", refs);
225
226
        // Are there currently outstanding references to the slot? If so, it
227
        // will have to be removed when those references are dropped.
228
0
        Some(refs.value == 0)
229
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::mark_release
230
231
    /// Mutates this slot.
232
    ///
233
    /// This method spins until no references to this slot are left, and calls the mutator
234
0
    fn release_with<F, M, R>(&self, gen: Generation<C>, offset: usize, free: &F, mutator: M) -> R
235
0
    where
236
0
        F: FreeList<C>,
237
0
        M: FnOnce(Option<&mut T>) -> R,
238
0
    {
239
0
        let mut lifecycle = self.lifecycle.load(Ordering::Acquire);
240
0
        let mut advanced = false;
241
0
        // Exponential spin backoff while waiting for the slot to be released.
242
0
        let mut spin_exp = 0;
243
0
        let next_gen = gen.advance();
244
        loop {
245
0
            let current_gen = LifecycleGen::from_packed(lifecycle).0;
246
0
            test_println!("-> release_with; lifecycle={:#x}; expected_gen={:?}; current_gen={:?}; next_gen={:?};",
247
0
                lifecycle,
248
0
                gen,
249
0
                current_gen,
250
0
                next_gen
251
0
            );
252
253
            // First, make sure we are actually able to remove the value.
254
            // If we're going to remove the value, the generation has to match
255
            // the value that `remove_value` was called with...unless we've
256
            // already stored the new generation.
257
0
            if (!advanced) && gen != current_gen {
258
0
                test_println!("-> already removed!");
259
0
                return mutator(None);
260
0
            }
261
0
262
0
            match self.lifecycle.compare_exchange(
263
0
                lifecycle,
264
0
                LifecycleGen(next_gen).pack(lifecycle),
265
0
                Ordering::AcqRel,
266
0
                Ordering::Acquire,
267
0
            ) {
268
0
                Ok(actual) => {
269
0
                    // If we're in this state, we have successfully advanced to
270
0
                    // the next generation.
271
0
                    advanced = true;
272
0
273
0
                    // Make sure that there are no outstanding references.
274
0
                    let refs = RefCount::<C>::from_packed(actual);
275
0
                    test_println!("-> advanced gen; lifecycle={:#x}; refs={:?};", actual, refs);
276
0
                    if refs.value == 0 {
277
0
                        test_println!("-> ok to remove!");
278
                        // safety: we've modified the generation of this slot and any other thread
279
                        // calling this method will exit out at the generation check above in the
280
                        // next iteraton of the loop.
281
0
                        let value = self
282
0
                            .item
283
0
                            .with_mut(|item| mutator(Some(unsafe { &mut *item })));
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::release_with::<_, _, _>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>::{closure#0}
284
0
                        free.push(offset, self);
285
0
                        return value;
286
0
                    }
287
0
288
0
                    // Otherwise, a reference must be dropped before we can
289
0
                    // remove the value. Spin here until there are no refs remaining...
290
0
                    test_println!("-> refs={:?}; spin...", refs);
291
292
                    // Back off, spinning and possibly yielding.
293
0
                    exponential_backoff(&mut spin_exp);
294
                }
295
0
                Err(actual) => {
296
0
                    test_println!("-> retrying; lifecycle={:#x};", actual);
297
0
                    lifecycle = actual;
298
0
                    // The state changed; reset the spin backoff.
299
0
                    spin_exp = 0;
300
                }
301
            }
302
        }
303
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::release_with::<_, _, _>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::Local, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::Local>::{closure#0}, bool>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release_with::<sharded_slab::page::stack::TransferStack, <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage<sharded_slab::page::stack::TransferStack>::{closure#0}, bool>
304
305
    /// Initialize a slot
306
    ///
307
    /// This method initializes and sets up the state for a slot. When being used in `Pool`, we
308
    /// only need to ensure that the `Slot` is in the right `state, while when being used in a
309
    /// `Slab` we want to insert a value into it, as the memory is not initialized
310
0
    pub(crate) fn init(&self) -> Option<InitGuard<T, C>> {
311
0
        // Load the current lifecycle state.
312
0
        let lifecycle = self.lifecycle.load(Ordering::Acquire);
313
0
        let gen = LifecycleGen::<C>::from_packed(lifecycle).0;
314
0
        let refs = RefCount::<C>::from_packed(lifecycle);
315
0
316
0
        test_println!(
317
            "-> initialize_state; state={:?}; gen={:?}; refs={:?};",
318
0
            Lifecycle::<C>::from_packed(lifecycle),
319
            gen,
320
            refs,
321
        );
322
323
0
        if refs.value != 0 {
324
0
            test_println!("-> initialize while referenced! cancelling");
325
0
            return None;
326
0
        }
327
0
328
0
        Some(InitGuard {
329
0
            slot: ptr::NonNull::from(self),
330
0
            curr_lifecycle: lifecycle,
331
0
            released: false,
332
0
        })
333
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::init
334
}
335
336
// Slot impl which _needs_ an `Option` for self.item, this is for `Slab` to use.
337
impl<T, C> Slot<Option<T>, C>
338
where
339
    C: cfg::Config,
340
{
341
0
    fn is_empty(&self) -> bool {
342
0
        self.item.with(|item| unsafe { (*item).is_none() })
343
0
    }
344
345
    /// Insert a value into a slot
346
    ///
347
    /// We first initialize the state and then insert the pased in value into the slot.
348
    #[inline]
349
0
    pub(crate) fn insert(&self, value: &mut Option<T>) -> Option<Generation<C>> {
350
0
        debug_assert!(self.is_empty(), "inserted into full slot");
351
0
        debug_assert!(value.is_some(), "inserted twice");
352
353
0
        let mut guard = self.init()?;
354
0
        let gen = guard.generation();
355
0
        unsafe {
356
0
            // Safety: Accessing the value of an `InitGuard` is unsafe because
357
0
            // it has a pointer to a slot which may dangle. Here, we know the
358
0
            // pointed slot is alive because we have a reference to it in scope,
359
0
            // and the `InitGuard` will be dropped when this function returns.
360
0
            mem::swap(guard.value_mut(), value);
361
0
            guard.release();
362
0
        };
363
0
        test_println!("-> inserted at {:?}", gen);
364
365
0
        Some(gen)
366
0
    }
367
368
    /// Tries to remove the value in the slot, returning `true` if the value was
369
    /// removed.
370
    ///
371
    /// This method tries to remove the value in the slot. If there are existing references, then
372
    /// the slot is marked for removal and the next thread calling either this method or
373
    /// `remove_value` will do the work instead.
374
    #[inline]
375
0
    pub(super) fn try_remove_value<F: FreeList<C>>(
376
0
        &self,
377
0
        gen: Generation<C>,
378
0
        offset: usize,
379
0
        free: &F,
380
0
    ) -> bool {
381
0
        let should_remove = match self.mark_release(gen) {
382
            // If `mark_release` returns `Some`, a value exists at this
383
            // generation. The bool inside this option indicates whether or not
384
            // _we're_ allowed to remove the value.
385
0
            Some(should_remove) => should_remove,
386
            // Otherwise, the generation we tried to remove has already expired,
387
            // and we did not mark anything for removal.
388
            None => {
389
0
                test_println!(
390
0
                    "-> try_remove_value; nothing exists at generation={:?}",
391
0
                    gen
392
0
                );
393
0
                return false;
394
            }
395
        };
396
397
0
        test_println!("-> try_remove_value; marked!");
398
399
0
        if should_remove {
400
            // We're allowed to remove the slot now!
401
0
            test_println!("-> try_remove_value; can remove now");
402
0
            self.remove_value(gen, offset, free);
403
0
        }
404
405
0
        true
406
0
    }
407
408
    #[inline]
409
0
    pub(super) fn remove_value<F: FreeList<C>>(
410
0
        &self,
411
0
        gen: Generation<C>,
412
0
        offset: usize,
413
0
        free: &F,
414
0
    ) -> Option<T> {
415
0
        self.release_with(gen, offset, free, |item| item.and_then(Option::take))
416
0
    }
417
}
418
419
// These impls are specific to `Pool`
420
impl<T, C> Slot<T, C>
421
where
422
    T: Default + Clear,
423
    C: cfg::Config,
424
{
425
0
    pub(in crate::page) fn new(next: usize) -> Self {
426
0
        Self {
427
0
            lifecycle: AtomicUsize::new(Lifecycle::<C>::REMOVING.as_usize()),
428
0
            item: UnsafeCell::new(T::default()),
429
0
            next: UnsafeCell::new(next),
430
0
            _cfg: PhantomData,
431
0
        }
432
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::new
433
434
    /// Try to clear this slot's storage
435
    ///
436
    /// If there are references to this slot, then we mark this slot for clearing and let the last
437
    /// thread do the work for us.
438
    #[inline]
439
0
    pub(super) fn try_clear_storage<F: FreeList<C>>(
440
0
        &self,
441
0
        gen: Generation<C>,
442
0
        offset: usize,
443
0
        free: &F,
444
0
    ) -> bool {
445
0
        let should_clear = match self.mark_release(gen) {
446
            // If `mark_release` returns `Some`, a value exists at this
447
            // generation. The bool inside this option indicates whether or not
448
            // _we're_ allowed to clear the value.
449
0
            Some(should_clear) => should_clear,
450
            // Otherwise, the generation we tried to remove has already expired,
451
            // and we did not mark anything for removal.
452
            None => {
453
0
                test_println!(
454
0
                    "-> try_clear_storage; nothing exists at generation={:?}",
455
0
                    gen
456
0
                );
457
0
                return false;
458
            }
459
        };
460
461
0
        test_println!("-> try_clear_storage; marked!");
462
463
0
        if should_clear {
464
            // We're allowed to remove the slot now!
465
0
            test_println!("-> try_remove_value; can clear now");
466
0
            return self.clear_storage(gen, offset, free);
467
0
        }
468
0
469
0
        true
470
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::try_clear_storage::<_>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::try_clear_storage::<sharded_slab::page::stack::TransferStack>
471
472
    /// Clear this slot's storage
473
    ///
474
    /// This method blocks until all references have been dropped and clears the storage.
475
0
    pub(super) fn clear_storage<F: FreeList<C>>(
476
0
        &self,
477
0
        gen: Generation<C>,
478
0
        offset: usize,
479
0
        free: &F,
480
0
    ) -> bool {
481
0
        // release_with will _always_ wait unitl it can release the slot or just return if the slot
482
0
        // has already been released.
483
0
        self.release_with(gen, offset, free, |item| {
484
0
            let cleared = item.map(|inner| Clear::clear(inner)).is_some();
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::clear_storage::<_>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}::{closure#0}
485
0
            test_println!("-> cleared: {}", cleared);
486
0
            cleared
487
0
        })
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::clear_storage::<_>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>::{closure#0}
488
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::clear_storage::<_>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::Local>
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::clear_storage::<sharded_slab::page::stack::TransferStack>
489
}
490
491
impl<T, C: cfg::Config> Slot<T, C> {
492
0
    fn release(&self) -> bool {
493
0
        let mut lifecycle = self.lifecycle.load(Ordering::Acquire);
494
        loop {
495
0
            let refs = RefCount::<C>::from_packed(lifecycle);
496
0
            let state = Lifecycle::<C>::from_packed(lifecycle).state;
497
0
            let gen = LifecycleGen::<C>::from_packed(lifecycle).0;
498
499
            // Are we the last guard, and is the slot marked for removal?
500
0
            let dropping = refs.value == 1 && state == State::Marked;
501
0
            let new_lifecycle = if dropping {
502
                // If so, we want to advance the state to "removing".
503
                // Also, reset the ref count to 0.
504
0
                LifecycleGen(gen).pack(State::Removing as usize)
505
            } else {
506
                // Otherwise, just subtract 1 from the ref count.
507
0
                refs.decr().pack(lifecycle)
508
            };
509
510
0
            test_println!(
511
0
                "-> drop guard: state={:?}; gen={:?}; refs={:?}; lifecycle={:#x}; new_lifecycle={:#x}; dropping={:?}",
512
0
                state,
513
0
                gen,
514
0
                refs,
515
0
                lifecycle,
516
0
                new_lifecycle,
517
0
                dropping
518
0
            );
519
0
            match self.lifecycle.compare_exchange(
520
0
                lifecycle,
521
0
                new_lifecycle,
522
0
                Ordering::AcqRel,
523
0
                Ordering::Acquire,
524
0
            ) {
525
                Ok(_) => {
526
0
                    test_println!("-> drop guard: done;  dropping={:?}", dropping);
527
0
                    return dropping;
528
                }
529
0
                Err(actual) => {
530
0
                    test_println!("-> drop guard; retry, actual={:#x}", actual);
531
0
                    lifecycle = actual;
532
                }
533
            }
534
        }
535
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<_, _>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Slot<tracing_subscriber::registry::sharded::DataInner, sharded_slab::cfg::DefaultConfig>>::release
536
}
537
538
impl<T, C: cfg::Config> fmt::Debug for Slot<T, C> {
539
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540
0
        let lifecycle = self.lifecycle.load(Ordering::Relaxed);
541
0
        f.debug_struct("Slot")
542
0
            .field("lifecycle", &format_args!("{:#x}", lifecycle))
543
0
            .field("state", &Lifecycle::<C>::from_packed(lifecycle).state)
544
0
            .field("gen", &LifecycleGen::<C>::from_packed(lifecycle).0)
545
0
            .field("refs", &RefCount::<C>::from_packed(lifecycle))
546
0
            .field("next", &self.next())
547
0
            .finish()
548
0
    }
549
}
550
551
// === impl Generation ===
552
553
impl<C> fmt::Debug for Generation<C> {
554
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
555
0
        f.debug_tuple("Generation").field(&self.value).finish()
556
0
    }
557
}
558
559
impl<C: cfg::Config> Generation<C> {
560
0
    fn advance(self) -> Self {
561
0
        Self::from_usize((self.value + 1) % Self::BITS)
562
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation<_>>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
Unexecuted instantiation: <sharded_slab::page::slot::Generation>::advance
563
}
564
565
impl<C: cfg::Config> PartialEq for Generation<C> {
566
0
    fn eq(&self, other: &Self) -> bool {
567
0
        self.value == other.value
568
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation<_> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Generation as core::cmp::PartialEq>::eq
569
}
570
571
impl<C: cfg::Config> Eq for Generation<C> {}
572
573
impl<C: cfg::Config> PartialOrd for Generation<C> {
574
0
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
575
0
        self.value.partial_cmp(&other.value)
576
0
    }
577
}
578
579
impl<C: cfg::Config> Ord for Generation<C> {
580
0
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
581
0
        self.value.cmp(&other.value)
582
0
    }
583
}
584
585
impl<C: cfg::Config> Clone for Generation<C> {
586
0
    fn clone(&self) -> Self {
587
0
        *self
588
0
    }
589
}
590
591
impl<C: cfg::Config> Copy for Generation<C> {}
592
593
// === impl Guard ===
594
595
impl<T, C: cfg::Config> Guard<T, C> {
596
    /// Releases the guard, returning `true` if the slot should be cleared.
597
    ///
598
    /// ## Safety
599
    ///
600
    /// This dereferences a raw pointer to the slot. The caller is responsible
601
    /// for ensuring that the `Guard` does not outlive the slab that contains
602
    /// the pointed slot. Failure to do so means this pointer may dangle.
603
    #[inline]
604
0
    pub(crate) unsafe fn release(&self) -> bool {
605
0
        self.slot().release()
606
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<_, _>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::release
607
608
    /// Returns a borrowed reference to the slot.
609
    ///
610
    /// ## Safety
611
    ///
612
    /// This dereferences a raw pointer to the slot. The caller is responsible
613
    /// for ensuring that the `Guard` does not outlive the slab that contains
614
    /// the pointed slot. Failure to do so means this pointer may dangle.
615
    #[inline]
616
0
    pub(crate) unsafe fn slot(&self) -> &Slot<T, C> {
617
0
        self.slot.as_ref()
618
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<_, _>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::slot
619
620
    /// Returns a borrowed reference to the slot's value.
621
    ///
622
    /// ## Safety
623
    ///
624
    /// This dereferences a raw pointer to the slot. The caller is responsible
625
    /// for ensuring that the `Guard` does not outlive the slab that contains
626
    /// the pointed slot. Failure to do so means this pointer may dangle.
627
    #[inline(always)]
628
0
    pub(crate) unsafe fn value(&self) -> &T {
629
0
        self.slot().item.with(|item| &*item)
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<_, _>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value::{closure#0}
630
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<_, _>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::page::slot::Guard<tracing_subscriber::registry::sharded::DataInner>>::value
631
}
632
633
// === impl Lifecycle ===
634
635
impl<C: cfg::Config> Lifecycle<C> {
636
    const MARKED: Self = Self {
637
        state: State::Marked,
638
        _cfg: PhantomData,
639
    };
640
    const REMOVING: Self = Self {
641
        state: State::Removing,
642
        _cfg: PhantomData,
643
    };
644
    const PRESENT: Self = Self {
645
        state: State::Present,
646
        _cfg: PhantomData,
647
    };
648
}
649
650
impl<C: cfg::Config> Pack<C> for Lifecycle<C> {
651
    const LEN: usize = 2;
652
    type Prev = ();
653
654
0
    fn from_usize(u: usize) -> Self {
655
0
        Self {
656
0
            state: match u & Self::MASK {
657
0
                0b00 => State::Present,
658
0
                0b01 => State::Marked,
659
0
                0b11 => State::Removing,
660
0
                bad => unreachable!("weird lifecycle {:#b}", bad),
661
            },
662
0
            _cfg: PhantomData,
663
0
        }
664
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<_> as sharded_slab::Pack<_>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
665
666
0
    fn as_usize(&self) -> usize {
667
0
        self.state as usize
668
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<_> as sharded_slab::Pack<_>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
669
}
670
671
impl<C> PartialEq for Lifecycle<C> {
672
0
    fn eq(&self, other: &Self) -> bool {
673
0
        self.state == other.state
674
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<_> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as core::cmp::PartialEq>::eq
675
}
676
677
impl<C> Eq for Lifecycle<C> {}
678
679
impl<C> fmt::Debug for Lifecycle<C> {
680
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681
0
        f.debug_tuple("Lifecycle").field(&self.state).finish()
682
0
    }
683
}
684
685
// === impl RefCount ===
686
687
impl<C: cfg::Config> Pack<C> for RefCount<C> {
688
    const LEN: usize = cfg::WIDTH - (Lifecycle::<C>::LEN + Generation::<C>::LEN);
689
    type Prev = Lifecycle<C>;
690
691
0
    fn from_usize(value: usize) -> Self {
692
0
        debug_assert!(value <= Self::BITS);
693
0
        Self {
694
0
            value,
695
0
            _cfg: PhantomData,
696
0
        }
697
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount<_> as sharded_slab::Pack<_>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
698
699
0
    fn as_usize(&self) -> usize {
700
0
        self.value
701
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount<_> as sharded_slab::Pack<_>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
702
}
703
704
impl<C: cfg::Config> RefCount<C> {
705
    pub(crate) const MAX: usize = Self::BITS - 1;
706
707
    #[inline]
708
0
    fn incr(self) -> Option<Self> {
709
0
        if self.value >= Self::MAX {
710
0
            test_println!("-> get: {}; MAX={}", self.value, RefCount::<C>::MAX);
711
0
            return None;
712
0
        }
713
0
714
0
        Some(Self::from_usize(self.value + 1))
715
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount<_>>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::incr
716
717
    #[inline]
718
0
    fn decr(self) -> Self {
719
0
        Self::from_usize(self.value - 1)
720
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount<_>>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
Unexecuted instantiation: <sharded_slab::page::slot::RefCount>::decr
721
}
722
723
impl<C> fmt::Debug for RefCount<C> {
724
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
725
0
        f.debug_tuple("RefCount").field(&self.value).finish()
726
0
    }
727
}
728
729
impl<C: cfg::Config> PartialEq for RefCount<C> {
730
0
    fn eq(&self, other: &Self) -> bool {
731
0
        self.value == other.value
732
0
    }
733
}
734
735
impl<C: cfg::Config> Eq for RefCount<C> {}
736
737
impl<C: cfg::Config> PartialOrd for RefCount<C> {
738
0
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
739
0
        self.value.partial_cmp(&other.value)
740
0
    }
741
}
742
743
impl<C: cfg::Config> Ord for RefCount<C> {
744
0
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
745
0
        self.value.cmp(&other.value)
746
0
    }
747
}
748
749
impl<C: cfg::Config> Clone for RefCount<C> {
750
0
    fn clone(&self) -> Self {
751
0
        *self
752
0
    }
753
}
754
755
impl<C: cfg::Config> Copy for RefCount<C> {}
756
757
// === impl LifecycleGen ===
758
759
impl<C: cfg::Config> Pack<C> for LifecycleGen<C> {
760
    const LEN: usize = Generation::<C>::LEN;
761
    type Prev = RefCount<C>;
762
763
0
    fn from_usize(value: usize) -> Self {
764
0
        Self(Generation::from_usize(value))
765
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<_> as sharded_slab::Pack<_>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_usize
766
767
0
    fn as_usize(&self) -> usize {
768
0
        self.0.as_usize()
769
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<_> as sharded_slab::Pack<_>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::as_usize
770
}
771
772
impl<T, C: cfg::Config> InitGuard<T, C> {
773
0
    pub(crate) fn generation(&self) -> Generation<C> {
774
0
        LifecycleGen::<C>::from_packed(self.curr_lifecycle).0
775
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<_, _>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::generation
776
777
    /// Returns a borrowed reference to the slot's value.
778
    ///
779
    /// ## Safety
780
    ///
781
    /// This dereferences a raw pointer to the slot. The caller is responsible
782
    /// for ensuring that the `InitGuard` does not outlive the slab that
783
    /// contains the pointed slot. Failure to do so means this pointer may
784
    /// dangle.
785
0
    pub(crate) unsafe fn value(&self) -> &T {
786
0
        self.slot.as_ref().item.with(|val| &*val)
787
0
    }
788
789
    /// Returns a mutably borrowed reference to the slot's value.
790
    ///
791
    /// ## Safety
792
    ///
793
    /// This dereferences a raw pointer to the slot. The caller is responsible
794
    /// for ensuring that the `InitGuard` does not outlive the slab that
795
    /// contains the pointed slot. Failure to do so means this pointer may
796
    /// dangle.
797
    ///
798
    /// It's safe to reference the slot mutably, though, because creating an
799
    /// `InitGuard` ensures there are no outstanding immutable references.
800
0
    pub(crate) unsafe fn value_mut(&mut self) -> &mut T {
801
0
        self.slot.as_ref().item.with_mut(|val| &mut *val)
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<_, _>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut::{closure#0}
802
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<_, _>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::value_mut
803
804
    /// Releases the guard, returning `true` if the slot should be cleared.
805
    ///
806
    /// ## Safety
807
    ///
808
    /// This dereferences a raw pointer to the slot. The caller is responsible
809
    /// for ensuring that the `InitGuard` does not outlive the slab that
810
    /// contains the pointed slot. Failure to do so means this pointer may
811
    /// dangle.
812
0
    pub(crate) unsafe fn release(&mut self) -> bool {
813
0
        self.release2(0)
814
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<_, _>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release
815
816
    /// Downgrades the guard to an immutable guard
817
    ///
818
    /// ## Safety
819
    ///
820
    /// This dereferences a raw pointer to the slot. The caller is responsible
821
    /// for ensuring that the `InitGuard` does not outlive the slab that
822
    /// contains the pointed slot. Failure to do so means this pointer may
823
    /// dangle.
824
0
    pub(crate) unsafe fn downgrade(&mut self) -> Guard<T, C> {
825
0
        let _ = self.release2(RefCount::<C>::from_usize(1).pack(0));
826
0
        Guard { slot: self.slot }
827
0
    }
828
829
0
    unsafe fn release2(&mut self, new_refs: usize) -> bool {
830
0
        test_println!(
831
            "InitGuard::release; curr_lifecycle={:?}; downgrading={}",
832
0
            Lifecycle::<C>::from_packed(self.curr_lifecycle),
833
0
            new_refs != 0,
834
        );
835
0
        if self.released {
836
0
            test_println!("-> already released!");
837
0
            return false;
838
0
        }
839
0
        self.released = true;
840
0
        let mut curr_lifecycle = self.curr_lifecycle;
841
0
        let slot = self.slot.as_ref();
842
0
        let new_lifecycle = LifecycleGen::<C>::from_packed(self.curr_lifecycle)
843
0
            .pack(Lifecycle::<C>::PRESENT.pack(new_refs));
844
0
845
0
        match slot.lifecycle.compare_exchange(
846
0
            curr_lifecycle,
847
0
            new_lifecycle,
848
0
            Ordering::AcqRel,
849
0
            Ordering::Acquire,
850
0
        ) {
851
            Ok(_) => {
852
0
                test_println!("--> advanced to PRESENT; done");
853
0
                return false;
854
            }
855
0
            Err(actual) => {
856
0
                test_println!(
857
                    "--> lifecycle changed; actual={:?}",
858
0
                    Lifecycle::<C>::from_packed(actual)
859
                );
860
0
                curr_lifecycle = actual;
861
            }
862
        }
863
864
        // if the state was no longer the prior state, we are now responsible
865
        // for releasing the slot.
866
        loop {
867
0
            let refs = RefCount::<C>::from_packed(curr_lifecycle);
868
0
            let state = Lifecycle::<C>::from_packed(curr_lifecycle).state;
869
0
870
0
            test_println!(
871
0
                "-> InitGuard::release; lifecycle={:#x}; state={:?}; refs={:?};",
872
0
                curr_lifecycle,
873
0
                state,
874
0
                refs,
875
0
            );
876
877
0
            debug_assert!(state == State::Marked || thread::panicking(), "state was not MARKED; someone else has removed the slot while we have exclusive access!\nactual={:?}", state);
878
0
            debug_assert!(refs.value == 0 || thread::panicking(), "ref count was not 0; someone else has referenced the slot while we have exclusive access!\nactual={:?}", refs);
879
880
0
            let new_lifecycle = LifecycleGen(self.generation()).pack(State::Removing as usize);
881
0
882
0
            match slot.lifecycle.compare_exchange(
883
0
                curr_lifecycle,
884
0
                new_lifecycle,
885
0
                Ordering::AcqRel,
886
0
                Ordering::Acquire,
887
0
            ) {
888
                Ok(_) => {
889
0
                    test_println!("-> InitGuard::RELEASE: done!");
890
0
                    return true;
891
                }
892
0
                Err(actual) => {
893
0
                    debug_assert!(thread::panicking(), "we should not have to retry this CAS!");
894
0
                    test_println!("-> InitGuard::release; retry, actual={:#x}", actual);
895
0
                    curr_lifecycle = actual;
896
                }
897
            }
898
        }
899
0
    }
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<_, _>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
Unexecuted instantiation: <sharded_slab::page::slot::InitGuard<tracing_subscriber::registry::sharded::DataInner>>::release2
900
}
901
902
// === helpers ===
903
904
#[inline(always)]
905
0
fn exponential_backoff(exp: &mut usize) {
906
    /// Maximum exponent we can back off to.
907
    const MAX_EXPONENT: usize = 8;
908
909
    // Issue 2^exp pause instructions.
910
0
    for _ in 0..(1 << *exp) {
911
0
        hint::spin_loop();
912
0
    }
913
914
0
    if *exp >= MAX_EXPONENT {
915
0
        // If we have reached the max backoff, also yield to the scheduler
916
0
        // explicitly.
917
0
        crate::sync::yield_now();
918
0
    } else {
919
0
        // Otherwise, increment the exponent.
920
0
        *exp += 1;
921
0
    }
922
0
}