Coverage Report

Created: 2025-07-11 06:53

/rust/registry/src/index.crates.io-6f17d22bba15001f/sharded-slab-0.1.7/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
//! A lock-free concurrent slab.
2
//!
3
//! Slabs provide pre-allocated storage for many instances of a single data
4
//! type. When a large number of values of a single type are required,
5
//! this can be more efficient than allocating each item individually. Since the
6
//! allocated items are the same size, memory fragmentation is reduced, and
7
//! creating and removing new items can be very cheap.
8
//!
9
//! This crate implements a lock-free concurrent slab, indexed by `usize`s.
10
//!
11
//! ## Usage
12
//!
13
//! First, add this to your `Cargo.toml`:
14
//!
15
//! ```toml
16
//! sharded-slab = "0.1.1"
17
//! ```
18
//!
19
//! This crate provides two  types, [`Slab`] and [`Pool`], which provide
20
//! slightly different APIs for using a sharded slab.
21
//!
22
//! [`Slab`] implements a slab for _storing_ small types, sharing them between
23
//! threads, and accessing them by index. New entries are allocated by
24
//! [inserting] data, moving it in by value. Similarly, entries may be
25
//! deallocated by [taking] from the slab, moving the value out. This API is
26
//! similar to a `Vec<Option<T>>`, but allowing lock-free concurrent insertion
27
//! and removal.
28
//!
29
//! In contrast, the [`Pool`] type provides an [object pool] style API for
30
//! _reusing storage_. Rather than constructing values and moving them into the
31
//! pool, as with [`Slab`], [allocating an entry][create] from the pool takes a
32
//! closure that's provided with a mutable reference to initialize the entry in
33
//! place. When entries are deallocated, they are [cleared] in place. Types
34
//! which own a heap allocation can be cleared by dropping any _data_ they
35
//! store, but retaining any previously-allocated capacity. This means that a
36
//! [`Pool`] may be used to reuse a set of existing heap allocations, reducing
37
//! allocator load.
38
//!
39
//! [inserting]: Slab::insert
40
//! [taking]: Slab::take
41
//! [create]: Pool::create
42
//! [cleared]: Clear
43
//! [object pool]: https://en.wikipedia.org/wiki/Object_pool_pattern
44
//!
45
//! # Examples
46
//!
47
//! Inserting an item into the slab, returning an index:
48
//! ```rust
49
//! # use sharded_slab::Slab;
50
//! let slab = Slab::new();
51
//!
52
//! let key = slab.insert("hello world").unwrap();
53
//! assert_eq!(slab.get(key).unwrap(), "hello world");
54
//! ```
55
//!
56
//! To share a slab across threads, it may be wrapped in an `Arc`:
57
//! ```rust
58
//! # use sharded_slab::Slab;
59
//! use std::sync::Arc;
60
//! let slab = Arc::new(Slab::new());
61
//!
62
//! let slab2 = slab.clone();
63
//! let thread2 = std::thread::spawn(move || {
64
//!     let key = slab2.insert("hello from thread two").unwrap();
65
//!     assert_eq!(slab2.get(key).unwrap(), "hello from thread two");
66
//!     key
67
//! });
68
//!
69
//! let key1 = slab.insert("hello from thread one").unwrap();
70
//! assert_eq!(slab.get(key1).unwrap(), "hello from thread one");
71
//!
72
//! // Wait for thread 2 to complete.
73
//! let key2 = thread2.join().unwrap();
74
//!
75
//! // The item inserted by thread 2 remains in the slab.
76
//! assert_eq!(slab.get(key2).unwrap(), "hello from thread two");
77
//!```
78
//!
79
//! If items in the slab must be mutated, a `Mutex` or `RwLock` may be used for
80
//! each item, providing granular locking of items rather than of the slab:
81
//!
82
//! ```rust
83
//! # use sharded_slab::Slab;
84
//! use std::sync::{Arc, Mutex};
85
//! let slab = Arc::new(Slab::new());
86
//!
87
//! let key = slab.insert(Mutex::new(String::from("hello world"))).unwrap();
88
//!
89
//! let slab2 = slab.clone();
90
//! let thread2 = std::thread::spawn(move || {
91
//!     let hello = slab2.get(key).expect("item missing");
92
//!     let mut hello = hello.lock().expect("mutex poisoned");
93
//!     *hello = String::from("hello everyone!");
94
//! });
95
//!
96
//! thread2.join().unwrap();
97
//!
98
//! let hello = slab.get(key).expect("item missing");
99
//! let mut hello = hello.lock().expect("mutex poisoned");
100
//! assert_eq!(hello.as_str(), "hello everyone!");
101
//! ```
102
//!
103
//! # Configuration
104
//!
105
//! For performance reasons, several values used by the slab are calculated as
106
//! constants. In order to allow users to tune the slab's parameters, we provide
107
//! a [`Config`] trait which defines these parameters as associated `consts`.
108
//! The `Slab` type is generic over a `C: Config` parameter.
109
//!
110
//! [`Config`]: trait.Config.html
111
//!
112
//! # Comparison with Similar Crates
113
//!
114
//! - [`slab`]: Carl Lerche's `slab` crate provides a slab implementation with a
115
//!   similar API, implemented by storing all data in a single vector.
116
//!
117
//!   Unlike `sharded_slab`, inserting and removing elements from the slab
118
//!   requires  mutable access. This means that if the slab is accessed
119
//!   concurrently by multiple threads, it is necessary for it to be protected
120
//!   by a `Mutex` or `RwLock`. Items may not be inserted or removed (or
121
//!   accessed, if a `Mutex` is used) concurrently, even when they are
122
//!   unrelated. In many cases, the lock can become a significant bottleneck. On
123
//!   the other hand, this crate allows separate indices in the slab to be
124
//!   accessed, inserted, and removed concurrently without requiring a global
125
//!   lock. Therefore, when the slab is shared across multiple threads, this
126
//!   crate offers significantly better performance than `slab`.
127
//!
128
//!   However, the lock free slab introduces some additional constant-factor
129
//!   overhead. This means that in use-cases where a slab is _not_ shared by
130
//!   multiple threads and locking is not required, this crate will likely offer
131
//!   slightly worse performance.
132
//!
133
//!   In summary: `sharded-slab` offers significantly improved performance in
134
//!   concurrent use-cases, while `slab` should be preferred in single-threaded
135
//!   use-cases.
136
//!
137
//! [`slab`]: https://crates.io/crates/loom
138
//!
139
//! # Safety and Correctness
140
//!
141
//! Most implementations of lock-free data structures in Rust require some
142
//! amount of unsafe code, and this crate is not an exception. In order to catch
143
//! potential bugs in this unsafe code, we make use of [`loom`], a
144
//! permutation-testing tool for concurrent Rust programs. All `unsafe` blocks
145
//! this crate occur in accesses to `loom` `UnsafeCell`s. This means that when
146
//! those accesses occur in this crate's tests, `loom` will assert that they are
147
//! valid under the C11 memory model across multiple permutations of concurrent
148
//! executions of those tests.
149
//!
150
//! In order to guard against the [ABA problem][aba], this crate makes use of
151
//! _generational indices_. Each slot in the slab tracks a generation counter
152
//! which is incremented every time a value is inserted into that slot, and the
153
//! indices returned by [`Slab::insert`] include the generation of the slot when
154
//! the value was inserted, packed into the high-order bits of the index. This
155
//! ensures that if a value is inserted, removed,  and a new value is inserted
156
//! into the same slot in the slab, the key returned by the first call to
157
//! `insert` will not map to the new value.
158
//!
159
//! Since a fixed number of bits are set aside to use for storing the generation
160
//! counter, the counter will wrap  around after being incremented a number of
161
//! times. To avoid situations where a returned index lives long enough to see the
162
//! generation counter wrap around to the same value, it is good to be fairly
163
//! generous when configuring the allocation of index bits.
164
//!
165
//! [`loom`]: https://crates.io/crates/loom
166
//! [aba]: https://en.wikipedia.org/wiki/ABA_problem
167
//! [`Slab::insert`]: struct.Slab.html#method.insert
168
//!
169
//! # Performance
170
//!
171
//! These graphs were produced by [benchmarks] of the sharded slab implementation,
172
//! using the [`criterion`] crate.
173
//!
174
//! The first shows the results of a benchmark where an increasing number of
175
//! items are inserted and then removed into a slab concurrently by five
176
//! threads. It compares the performance of the sharded slab implementation
177
//! with a `RwLock<slab::Slab>`:
178
//!
179
//! <img width="1124" alt="Screen Shot 2019-10-01 at 5 09 49 PM" src="https://user-images.githubusercontent.com/2796466/66078398-cd6c9f80-e516-11e9-9923-0ed6292e8498.png">
180
//!
181
//! The second graph shows the results of a benchmark where an increasing
182
//! number of items are inserted and then removed by a _single_ thread. It
183
//! compares the performance of the sharded slab implementation with an
184
//! `RwLock<slab::Slab>` and a `mut slab::Slab`.
185
//!
186
//! <img width="925" alt="Screen Shot 2019-10-01 at 5 13 45 PM" src="https://user-images.githubusercontent.com/2796466/66078469-f0974f00-e516-11e9-95b5-f65f0aa7e494.png">
187
//!
188
//! These benchmarks demonstrate that, while the sharded approach introduces
189
//! a small constant-factor overhead, it offers significantly better
190
//! performance across concurrent accesses.
191
//!
192
//! [benchmarks]: https://github.com/hawkw/sharded-slab/blob/master/benches/bench.rs
193
//! [`criterion`]: https://crates.io/crates/criterion
194
//!
195
//! # Implementation Notes
196
//!
197
//! See [this page](crate::implementation) for details on this crate's design
198
//! and implementation.
199
//!
200
#![doc(html_root_url = "https://docs.rs/sharded-slab/0.1.4")]
201
#![warn(missing_debug_implementations, missing_docs)]
202
#![cfg_attr(docsrs, warn(rustdoc::broken_intra_doc_links))]
203
#[macro_use]
204
mod macros;
205
206
pub mod implementation;
207
pub mod pool;
208
209
pub(crate) mod cfg;
210
pub(crate) mod sync;
211
212
mod clear;
213
mod iter;
214
mod page;
215
mod shard;
216
mod tid;
217
218
pub use self::{
219
    cfg::{Config, DefaultConfig},
220
    clear::Clear,
221
    iter::UniqueIter,
222
};
223
#[doc(inline)]
224
pub use pool::Pool;
225
226
pub(crate) use tid::Tid;
227
228
use cfg::CfgPrivate;
229
use shard::Shard;
230
use std::{fmt, marker::PhantomData, ptr, sync::Arc};
231
232
/// A sharded slab.
233
///
234
/// See the [crate-level documentation](crate) for details on using this type.
235
pub struct Slab<T, C: cfg::Config = DefaultConfig> {
236
    shards: shard::Array<Option<T>, C>,
237
    _cfg: PhantomData<C>,
238
}
239
240
/// A handle that allows access to an occupied entry in a [`Slab`].
241
///
242
/// While the guard exists, it indicates to the slab that the item the guard
243
/// references is currently being accessed. If the item is removed from the slab
244
/// while a guard exists, the removal will be deferred until all guards are
245
/// dropped.
246
pub struct Entry<'a, T, C: cfg::Config = DefaultConfig> {
247
    inner: page::slot::Guard<Option<T>, C>,
248
    value: ptr::NonNull<T>,
249
    shard: &'a Shard<Option<T>, C>,
250
    key: usize,
251
}
252
253
/// A handle to a vacant entry in a [`Slab`].
254
///
255
/// `VacantEntry` allows constructing values with the key that they will be
256
/// assigned to.
257
///
258
/// # Examples
259
///
260
/// ```
261
/// # use sharded_slab::Slab;
262
/// let mut slab = Slab::new();
263
///
264
/// let hello = {
265
///     let entry = slab.vacant_entry().unwrap();
266
///     let key = entry.key();
267
///
268
///     entry.insert((key, "hello"));
269
///     key
270
/// };
271
///
272
/// assert_eq!(hello, slab.get(hello).unwrap().0);
273
/// assert_eq!("hello", slab.get(hello).unwrap().1);
274
/// ```
275
#[derive(Debug)]
276
pub struct VacantEntry<'a, T, C: cfg::Config = DefaultConfig> {
277
    inner: page::slot::InitGuard<Option<T>, C>,
278
    key: usize,
279
    _lt: PhantomData<&'a ()>,
280
}
281
282
/// An owned reference to an occupied entry in a [`Slab`].
283
///
284
/// While the guard exists, it indicates to the slab that the item the guard
285
/// references is currently being accessed. If the item is removed from the slab
286
/// while the guard exists, the  removal will be deferred until all guards are
287
/// dropped.
288
///
289
/// Unlike [`Entry`], which borrows the slab, an `OwnedEntry` clones the [`Arc`]
290
/// around the slab. Therefore, it keeps the slab from being dropped until all
291
/// such guards have been dropped. This means that an `OwnedEntry` may be held for
292
/// an arbitrary lifetime.
293
///
294
/// # Examples
295
///
296
/// ```
297
/// # use sharded_slab::Slab;
298
/// use std::sync::Arc;
299
///
300
/// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
301
/// let key = slab.insert("hello world").unwrap();
302
///
303
/// // Look up the created key, returning an `OwnedEntry`.
304
/// let value = slab.clone().get_owned(key).unwrap();
305
///
306
/// // Now, the original `Arc` clone of the slab may be dropped, but the
307
/// // returned `OwnedEntry` can still access the value.
308
/// assert_eq!(value, "hello world");
309
/// ```
310
///
311
/// Unlike [`Entry`], an `OwnedEntry` may be stored in a struct which must live
312
/// for the `'static` lifetime:
313
///
314
/// ```
315
/// # use sharded_slab::Slab;
316
/// use sharded_slab::OwnedEntry;
317
/// use std::sync::Arc;
318
///
319
/// pub struct MyStruct {
320
///     entry: OwnedEntry<&'static str>,
321
///     // ... other fields ...
322
/// }
323
///
324
/// // Suppose this is some arbitrary function which requires a value that
325
/// // lives for the 'static lifetime...
326
/// fn function_requiring_static<T: 'static>(t: &T) {
327
///     // ... do something extremely important and interesting ...
328
/// }
329
///
330
/// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
331
/// let key = slab.insert("hello world").unwrap();
332
///
333
/// // Look up the created key, returning an `OwnedEntry`.
334
/// let entry = slab.clone().get_owned(key).unwrap();
335
/// let my_struct = MyStruct {
336
///     entry,
337
///     // ...
338
/// };
339
///
340
/// // We can use `my_struct` anywhere where it is required to have the
341
/// // `'static` lifetime:
342
/// function_requiring_static(&my_struct);
343
/// ```
344
///
345
/// `OwnedEntry`s may be sent between threads:
346
///
347
/// ```
348
/// # use sharded_slab::Slab;
349
/// use std::{thread, sync::Arc};
350
///
351
/// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
352
/// let key = slab.insert("hello world").unwrap();
353
///
354
/// // Look up the created key, returning an `OwnedEntry`.
355
/// let value = slab.clone().get_owned(key).unwrap();
356
///
357
/// thread::spawn(move || {
358
///     assert_eq!(value, "hello world");
359
///     // ...
360
/// }).join().unwrap();
361
/// ```
362
///
363
/// [`get`]: Slab::get
364
/// [`Arc`]: std::sync::Arc
365
pub struct OwnedEntry<T, C = DefaultConfig>
366
where
367
    C: cfg::Config,
368
{
369
    inner: page::slot::Guard<Option<T>, C>,
370
    value: ptr::NonNull<T>,
371
    slab: Arc<Slab<T, C>>,
372
    key: usize,
373
}
374
375
impl<T> Slab<T> {
376
    /// Returns a new slab with the default configuration parameters.
377
0
    pub fn new() -> Self {
378
0
        Self::new_with_config()
379
0
    }
380
381
    /// Returns a new slab with the provided configuration parameters.
382
0
    pub fn new_with_config<C: cfg::Config>() -> Slab<T, C> {
383
0
        C::validate();
384
0
        Slab {
385
0
            shards: shard::Array::new(),
386
0
            _cfg: PhantomData,
387
0
        }
388
0
    }
389
}
390
391
impl<T, C: cfg::Config> Slab<T, C> {
392
    /// The number of bits in each index which are used by the slab.
393
    ///
394
    /// If other data is packed into the `usize` indices returned by
395
    /// [`Slab::insert`], user code is free to use any bits higher than the
396
    /// `USED_BITS`-th bit freely.
397
    ///
398
    /// This is determined by the [`Config`] type that configures the slab's
399
    /// parameters. By default, all bits are used; this can be changed by
400
    /// overriding the [`Config::RESERVED_BITS`][res] constant.
401
    ///
402
    /// [res]: crate::Config#RESERVED_BITS
403
    pub const USED_BITS: usize = C::USED_BITS;
404
405
    /// Inserts a value into the slab, returning the integer index at which that
406
    /// value was inserted. This index can then be used to access the entry.
407
    ///
408
    /// If this function returns `None`, then the shard for the current thread
409
    /// is full and no items can be added until some are removed, or the maximum
410
    /// number of shards has been reached.
411
    ///
412
    /// # Examples
413
    /// ```rust
414
    /// # use sharded_slab::Slab;
415
    /// let slab = Slab::new();
416
    ///
417
    /// let key = slab.insert("hello world").unwrap();
418
    /// assert_eq!(slab.get(key).unwrap(), "hello world");
419
    /// ```
420
0
    pub fn insert(&self, value: T) -> Option<usize> {
421
0
        let (tid, shard) = self.shards.current();
422
0
        test_println!("insert {:?}", tid);
423
0
        let mut value = Some(value);
424
0
        shard
425
0
            .init_with(|idx, slot| {
426
0
                let gen = slot.insert(&mut value)?;
427
0
                Some(gen.pack(idx))
428
0
            })
429
0
            .map(|idx| tid.pack(idx))
430
0
    }
431
432
    /// Return a handle to a vacant entry allowing for further manipulation.
433
    ///
434
    /// This function is useful when creating values that must contain their
435
    /// slab index. The returned [`VacantEntry`] reserves a slot in the slab and
436
    /// is able to return the index of the entry.
437
    ///
438
    /// # Examples
439
    ///
440
    /// ```
441
    /// # use sharded_slab::Slab;
442
    /// let mut slab = Slab::new();
443
    ///
444
    /// let hello = {
445
    ///     let entry = slab.vacant_entry().unwrap();
446
    ///     let key = entry.key();
447
    ///
448
    ///     entry.insert((key, "hello"));
449
    ///     key
450
    /// };
451
    ///
452
    /// assert_eq!(hello, slab.get(hello).unwrap().0);
453
    /// assert_eq!("hello", slab.get(hello).unwrap().1);
454
    /// ```
455
0
    pub fn vacant_entry(&self) -> Option<VacantEntry<'_, T, C>> {
456
0
        let (tid, shard) = self.shards.current();
457
0
        test_println!("vacant_entry {:?}", tid);
458
0
        shard.init_with(|idx, slot| {
459
0
            let inner = slot.init()?;
460
0
            let key = inner.generation().pack(tid.pack(idx));
461
0
            Some(VacantEntry {
462
0
                inner,
463
0
                key,
464
0
                _lt: PhantomData,
465
0
            })
466
0
        })
467
0
    }
468
469
    /// Remove the value at the given index in the slab, returning `true` if a
470
    /// value was removed.
471
    ///
472
    /// Unlike [`take`], this method does _not_ block the current thread until
473
    /// the value can be removed. Instead, if another thread is currently
474
    /// accessing that value, this marks it to be removed by that thread when it
475
    /// finishes accessing the value.
476
    ///
477
    /// # Examples
478
    ///
479
    /// ```rust
480
    /// let slab = sharded_slab::Slab::new();
481
    /// let key = slab.insert("hello world").unwrap();
482
    ///
483
    /// // Remove the item from the slab.
484
    /// assert!(slab.remove(key));
485
    ///
486
    /// // Now, the slot is empty.
487
    /// assert!(!slab.contains(key));
488
    /// ```
489
    ///
490
    /// ```rust
491
    /// use std::sync::Arc;
492
    ///
493
    /// let slab = Arc::new(sharded_slab::Slab::new());
494
    /// let key = slab.insert("hello world").unwrap();
495
    ///
496
    /// let slab2 = slab.clone();
497
    /// let thread2 = std::thread::spawn(move || {
498
    ///     // Depending on when this thread begins executing, the item may
499
    ///     // or may not have already been removed...
500
    ///     if let Some(item) = slab2.get(key) {
501
    ///         assert_eq!(item, "hello world");
502
    ///     }
503
    /// });
504
    ///
505
    /// // The item will be removed by thread2 when it finishes accessing it.
506
    /// assert!(slab.remove(key));
507
    ///
508
    /// thread2.join().unwrap();
509
    /// assert!(!slab.contains(key));
510
    /// ```
511
    /// [`take`]: Slab::take
512
0
    pub fn remove(&self, idx: usize) -> bool {
513
0
        // The `Drop` impl for `Entry` calls `remove_local` or `remove_remote` based
514
0
        // on where the guard was dropped from. If the dropped guard was the last one, this will
515
0
        // call `Slot::remove_value` which actually clears storage.
516
0
        let tid = C::unpack_tid(idx);
517
0
518
0
        test_println!("rm_deferred {:?}", tid);
519
0
        let shard = self.shards.get(tid.as_usize());
520
0
        if tid.is_current() {
521
0
            shard.map(|shard| shard.remove_local(idx)).unwrap_or(false)
522
        } else {
523
0
            shard.map(|shard| shard.remove_remote(idx)).unwrap_or(false)
524
        }
525
0
    }
526
527
    /// Removes the value associated with the given key from the slab, returning
528
    /// it.
529
    ///
530
    /// If the slab does not contain a value for that key, `None` is returned
531
    /// instead.
532
    ///
533
    /// If the value associated with the given key is currently being
534
    /// accessed by another thread, this method will block the current thread
535
    /// until the item is no longer accessed. If this is not desired, use
536
    /// [`remove`] instead.
537
    ///
538
    /// **Note**: This method blocks the calling thread by spinning until the
539
    /// currently outstanding references are released. Spinning for long periods
540
    /// of time can result in high CPU time and power consumption. Therefore,
541
    /// `take` should only be called when other references to the slot are
542
    /// expected to be dropped soon (e.g., when all accesses are relatively
543
    /// short).
544
    ///
545
    /// # Examples
546
    ///
547
    /// ```rust
548
    /// let slab = sharded_slab::Slab::new();
549
    /// let key = slab.insert("hello world").unwrap();
550
    ///
551
    /// // Remove the item from the slab, returning it.
552
    /// assert_eq!(slab.take(key), Some("hello world"));
553
    ///
554
    /// // Now, the slot is empty.
555
    /// assert!(!slab.contains(key));
556
    /// ```
557
    ///
558
    /// ```rust
559
    /// use std::sync::Arc;
560
    ///
561
    /// let slab = Arc::new(sharded_slab::Slab::new());
562
    /// let key = slab.insert("hello world").unwrap();
563
    ///
564
    /// let slab2 = slab.clone();
565
    /// let thread2 = std::thread::spawn(move || {
566
    ///     // Depending on when this thread begins executing, the item may
567
    ///     // or may not have already been removed...
568
    ///     if let Some(item) = slab2.get(key) {
569
    ///         assert_eq!(item, "hello world");
570
    ///     }
571
    /// });
572
    ///
573
    /// // The item will only be removed when the other thread finishes
574
    /// // accessing it.
575
    /// assert_eq!(slab.take(key), Some("hello world"));
576
    ///
577
    /// thread2.join().unwrap();
578
    /// assert!(!slab.contains(key));
579
    /// ```
580
    /// [`remove`]: Slab::remove
581
0
    pub fn take(&self, idx: usize) -> Option<T> {
582
0
        let tid = C::unpack_tid(idx);
583
0
584
0
        test_println!("rm {:?}", tid);
585
0
        let shard = self.shards.get(tid.as_usize())?;
586
0
        if tid.is_current() {
587
0
            shard.take_local(idx)
588
        } else {
589
0
            shard.take_remote(idx)
590
        }
591
0
    }
592
593
    /// Return a reference to the value associated with the given key.
594
    ///
595
    /// If the slab does not contain a value for the given key, or if the
596
    /// maximum number of concurrent references to the slot has been reached,
597
    /// `None` is returned instead.
598
    ///
599
    /// # Examples
600
    ///
601
    /// ```rust
602
    /// let slab = sharded_slab::Slab::new();
603
    /// let key = slab.insert("hello world").unwrap();
604
    ///
605
    /// assert_eq!(slab.get(key).unwrap(), "hello world");
606
    /// assert!(slab.get(12345).is_none());
607
    /// ```
608
0
    pub fn get(&self, key: usize) -> Option<Entry<'_, T, C>> {
609
0
        let tid = C::unpack_tid(key);
610
0
611
0
        test_println!("get {:?}; current={:?}", tid, Tid::<C>::current());
612
0
        let shard = self.shards.get(tid.as_usize())?;
613
0
        shard.with_slot(key, |slot| {
614
0
            let inner = slot.get(C::unpack_gen(key))?;
615
0
            let value = ptr::NonNull::from(slot.value().as_ref().unwrap());
616
0
            Some(Entry {
617
0
                inner,
618
0
                value,
619
0
                shard,
620
0
                key,
621
0
            })
622
0
        })
623
0
    }
624
625
    /// Return an owned reference to the value at the given index.
626
    ///
627
    /// If the slab does not contain a value for the given key, `None` is
628
    /// returned instead.
629
    ///
630
    /// Unlike [`get`], which borrows the slab, this method _clones_ the [`Arc`]
631
    /// around the slab. This means that the returned [`OwnedEntry`] can be held
632
    /// for an arbitrary lifetime. However,  this method requires that the slab
633
    /// itself be wrapped in an `Arc`.
634
    ///
635
    /// # Examples
636
    ///
637
    /// ```
638
    /// # use sharded_slab::Slab;
639
    /// use std::sync::Arc;
640
    ///
641
    /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
642
    /// let key = slab.insert("hello world").unwrap();
643
    ///
644
    /// // Look up the created key, returning an `OwnedEntry`.
645
    /// let value = slab.clone().get_owned(key).unwrap();
646
    ///
647
    /// // Now, the original `Arc` clone of the slab may be dropped, but the
648
    /// // returned `OwnedEntry` can still access the value.
649
    /// assert_eq!(value, "hello world");
650
    /// ```
651
    ///
652
    /// Unlike [`Entry`], an `OwnedEntry` may be stored in a struct which must live
653
    /// for the `'static` lifetime:
654
    ///
655
    /// ```
656
    /// # use sharded_slab::Slab;
657
    /// use sharded_slab::OwnedEntry;
658
    /// use std::sync::Arc;
659
    ///
660
    /// pub struct MyStruct {
661
    ///     entry: OwnedEntry<&'static str>,
662
    ///     // ... other fields ...
663
    /// }
664
    ///
665
    /// // Suppose this is some arbitrary function which requires a value that
666
    /// // lives for the 'static lifetime...
667
    /// fn function_requiring_static<T: 'static>(t: &T) {
668
    ///     // ... do something extremely important and interesting ...
669
    /// }
670
    ///
671
    /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
672
    /// let key = slab.insert("hello world").unwrap();
673
    ///
674
    /// // Look up the created key, returning an `OwnedEntry`.
675
    /// let entry = slab.clone().get_owned(key).unwrap();
676
    /// let my_struct = MyStruct {
677
    ///     entry,
678
    ///     // ...
679
    /// };
680
    ///
681
    /// // We can use `my_struct` anywhere where it is required to have the
682
    /// // `'static` lifetime:
683
    /// function_requiring_static(&my_struct);
684
    /// ```
685
    ///
686
    /// [`OwnedEntry`]s may be sent between threads:
687
    ///
688
    /// ```
689
    /// # use sharded_slab::Slab;
690
    /// use std::{thread, sync::Arc};
691
    ///
692
    /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new());
693
    /// let key = slab.insert("hello world").unwrap();
694
    ///
695
    /// // Look up the created key, returning an `OwnedEntry`.
696
    /// let value = slab.clone().get_owned(key).unwrap();
697
    ///
698
    /// thread::spawn(move || {
699
    ///     assert_eq!(value, "hello world");
700
    ///     // ...
701
    /// }).join().unwrap();
702
    /// ```
703
    ///
704
    /// [`get`]: Slab::get
705
    /// [`Arc`]: std::sync::Arc
706
0
    pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedEntry<T, C>> {
707
0
        let tid = C::unpack_tid(key);
708
0
709
0
        test_println!("get_owned {:?}; current={:?}", tid, Tid::<C>::current());
710
0
        let shard = self.shards.get(tid.as_usize())?;
711
0
        shard.with_slot(key, |slot| {
712
0
            let inner = slot.get(C::unpack_gen(key))?;
713
0
            let value = ptr::NonNull::from(slot.value().as_ref().unwrap());
714
0
            Some(OwnedEntry {
715
0
                inner,
716
0
                value,
717
0
                slab: self.clone(),
718
0
                key,
719
0
            })
720
0
        })
721
0
    }
722
723
    /// Returns `true` if the slab contains a value for the given key.
724
    ///
725
    /// # Examples
726
    ///
727
    /// ```
728
    /// let slab = sharded_slab::Slab::new();
729
    ///
730
    /// let key = slab.insert("hello world").unwrap();
731
    /// assert!(slab.contains(key));
732
    ///
733
    /// slab.take(key).unwrap();
734
    /// assert!(!slab.contains(key));
735
    /// ```
736
0
    pub fn contains(&self, key: usize) -> bool {
737
0
        self.get(key).is_some()
738
0
    }
739
740
    /// Returns an iterator over all the items in the slab.
741
    ///
742
    /// Because this iterator exclusively borrows the slab (i.e. it holds an
743
    /// `&mut Slab<T>`), elements will not be added or removed while the
744
    /// iteration is in progress.
745
0
    pub fn unique_iter(&mut self) -> iter::UniqueIter<'_, T, C> {
746
0
        let mut shards = self.shards.iter_mut();
747
748
0
        let (pages, slots) = match shards.next() {
749
0
            Some(shard) => {
750
0
                let mut pages = shard.iter();
751
0
                let slots = pages.next().and_then(page::Shared::iter);
752
0
                (pages, slots)
753
            }
754
0
            None => ([].iter(), None),
755
        };
756
757
0
        iter::UniqueIter {
758
0
            shards,
759
0
            pages,
760
0
            slots,
761
0
        }
762
0
    }
763
}
764
765
impl<T> Default for Slab<T> {
766
0
    fn default() -> Self {
767
0
        Self::new()
768
0
    }
769
}
770
771
impl<T: fmt::Debug, C: cfg::Config> fmt::Debug for Slab<T, C> {
772
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
773
0
        f.debug_struct("Slab")
774
0
            .field("shards", &self.shards)
775
0
            .field("config", &C::debug())
776
0
            .finish()
777
0
    }
778
}
779
780
unsafe impl<T: Send, C: cfg::Config> Send for Slab<T, C> {}
781
unsafe impl<T: Sync, C: cfg::Config> Sync for Slab<T, C> {}
782
783
// === impl Entry ===
784
785
impl<'a, T, C: cfg::Config> Entry<'a, T, C> {
786
    /// Returns the key used to access the guard.
787
0
    pub fn key(&self) -> usize {
788
0
        self.key
789
0
    }
790
791
    #[inline(always)]
792
0
    fn value(&self) -> &T {
793
0
        unsafe {
794
0
            // Safety: this is always going to be valid, as it's projected from
795
0
            // the safe reference to `self.value` --- this is just to avoid
796
0
            // having to `expect` an option in the hot path when dereferencing.
797
0
            self.value.as_ref()
798
0
        }
799
0
    }
800
}
801
802
impl<'a, T, C: cfg::Config> std::ops::Deref for Entry<'a, T, C> {
803
    type Target = T;
804
805
0
    fn deref(&self) -> &Self::Target {
806
0
        self.value()
807
0
    }
808
}
809
810
impl<'a, T, C: cfg::Config> Drop for Entry<'a, T, C> {
811
0
    fn drop(&mut self) {
812
0
        let should_remove = unsafe {
813
0
            // Safety: calling `slot::Guard::release` is unsafe, since the
814
0
            // `Guard` value contains a pointer to the slot that may outlive the
815
0
            // slab containing that slot. Here, the `Entry` guard owns a
816
0
            // borrowed reference to the shard containing that slot, which
817
0
            // ensures that the slot will not be dropped while this `Guard`
818
0
            // exists.
819
0
            self.inner.release()
820
0
        };
821
0
        if should_remove {
822
0
            self.shard.clear_after_release(self.key)
823
0
        }
824
0
    }
825
}
826
827
impl<'a, T, C> fmt::Debug for Entry<'a, T, C>
828
where
829
    T: fmt::Debug,
830
    C: cfg::Config,
831
{
832
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833
0
        fmt::Debug::fmt(self.value(), f)
834
0
    }
835
}
836
837
impl<'a, T, C> PartialEq<T> for Entry<'a, T, C>
838
where
839
    T: PartialEq<T>,
840
    C: cfg::Config,
841
{
842
0
    fn eq(&self, other: &T) -> bool {
843
0
        self.value().eq(other)
844
0
    }
845
}
846
847
// === impl VacantEntry ===
848
849
impl<'a, T, C: cfg::Config> VacantEntry<'a, T, C> {
850
    /// Insert a value in the entry.
851
    ///
852
    /// To get the integer index at which this value will be inserted, use
853
    /// [`key`] prior to calling `insert`.
854
    ///
855
    /// # Examples
856
    ///
857
    /// ```
858
    /// # use sharded_slab::Slab;
859
    /// let mut slab = Slab::new();
860
    ///
861
    /// let hello = {
862
    ///     let entry = slab.vacant_entry().unwrap();
863
    ///     let key = entry.key();
864
    ///
865
    ///     entry.insert((key, "hello"));
866
    ///     key
867
    /// };
868
    ///
869
    /// assert_eq!(hello, slab.get(hello).unwrap().0);
870
    /// assert_eq!("hello", slab.get(hello).unwrap().1);
871
    /// ```
872
    ///
873
    /// [`key`]: VacantEntry::key
874
0
    pub fn insert(mut self, val: T) {
875
0
        let value = unsafe {
876
0
            // Safety: this `VacantEntry` only lives as long as the `Slab` it was
877
0
            // borrowed from, so it cannot outlive the entry's slot.
878
0
            self.inner.value_mut()
879
0
        };
880
0
        debug_assert!(
881
0
            value.is_none(),
882
            "tried to insert to a slot that already had a value!"
883
        );
884
0
        *value = Some(val);
885
0
        let _released = unsafe {
886
0
            // Safety: again, this `VacantEntry` only lives as long as the
887
0
            // `Slab` it was borrowed from, so it cannot outlive the entry's
888
0
            // slot.
889
0
            self.inner.release()
890
0
        };
891
0
        debug_assert!(
892
0
            !_released,
893
            "removing a value before it was inserted should be a no-op"
894
        )
895
0
    }
896
897
    /// Return the integer index at which this entry will be inserted.
898
    ///
899
    /// A value stored in this entry will be associated with this key.
900
    ///
901
    /// # Examples
902
    ///
903
    /// ```
904
    /// # use sharded_slab::*;
905
    /// let mut slab = Slab::new();
906
    ///
907
    /// let hello = {
908
    ///     let entry = slab.vacant_entry().unwrap();
909
    ///     let key = entry.key();
910
    ///
911
    ///     entry.insert((key, "hello"));
912
    ///     key
913
    /// };
914
    ///
915
    /// assert_eq!(hello, slab.get(hello).unwrap().0);
916
    /// assert_eq!("hello", slab.get(hello).unwrap().1);
917
    /// ```
918
0
    pub fn key(&self) -> usize {
919
0
        self.key
920
0
    }
921
}
922
// === impl OwnedEntry ===
923
924
impl<T, C> OwnedEntry<T, C>
925
where
926
    C: cfg::Config,
927
{
928
    /// Returns the key used to access this guard
929
0
    pub fn key(&self) -> usize {
930
0
        self.key
931
0
    }
932
933
    #[inline(always)]
934
0
    fn value(&self) -> &T {
935
0
        unsafe {
936
0
            // Safety: this is always going to be valid, as it's projected from
937
0
            // the safe reference to `self.value` --- this is just to avoid
938
0
            // having to `expect` an option in the hot path when dereferencing.
939
0
            self.value.as_ref()
940
0
        }
941
0
    }
942
}
943
944
impl<T, C> std::ops::Deref for OwnedEntry<T, C>
945
where
946
    C: cfg::Config,
947
{
948
    type Target = T;
949
950
0
    fn deref(&self) -> &Self::Target {
951
0
        self.value()
952
0
    }
953
}
954
955
impl<T, C> Drop for OwnedEntry<T, C>
956
where
957
    C: cfg::Config,
958
{
959
0
    fn drop(&mut self) {
960
0
        test_println!("drop OwnedEntry: try clearing data");
961
0
        let should_clear = unsafe {
962
0
            // Safety: calling `slot::Guard::release` is unsafe, since the
963
0
            // `Guard` value contains a pointer to the slot that may outlive the
964
0
            // slab containing that slot. Here, the `OwnedEntry` owns an `Arc`
965
0
            // clone of the pool, which keeps it alive as long as the `OwnedEntry`
966
0
            // exists.
967
0
            self.inner.release()
968
0
        };
969
0
        if should_clear {
970
0
            let shard_idx = Tid::<C>::from_packed(self.key);
971
0
            test_println!("-> shard={:?}", shard_idx);
972
0
            if let Some(shard) = self.slab.shards.get(shard_idx.as_usize()) {
973
0
                shard.clear_after_release(self.key)
974
            } else {
975
0
                test_println!("-> shard={:?} does not exist! THIS IS A BUG", shard_idx);
976
0
                debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedEntry` to a slot on a shard that never existed!");
977
            }
978
0
        }
979
0
    }
980
}
981
982
impl<T, C> fmt::Debug for OwnedEntry<T, C>
983
where
984
    T: fmt::Debug,
985
    C: cfg::Config,
986
{
987
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
988
0
        fmt::Debug::fmt(self.value(), f)
989
0
    }
990
}
991
992
impl<T, C> PartialEq<T> for OwnedEntry<T, C>
993
where
994
    T: PartialEq<T>,
995
    C: cfg::Config,
996
{
997
0
    fn eq(&self, other: &T) -> bool {
998
0
        *self.value() == *other
999
0
    }
1000
}
1001
1002
unsafe impl<T, C> Sync for OwnedEntry<T, C>
1003
where
1004
    T: Sync,
1005
    C: cfg::Config,
1006
{
1007
}
1008
1009
unsafe impl<T, C> Send for OwnedEntry<T, C>
1010
where
1011
    T: Sync,
1012
    C: cfg::Config,
1013
{
1014
}
1015
1016
// === pack ===
1017
1018
pub(crate) trait Pack<C: cfg::Config>: Sized {
1019
    // ====== provided by each implementation =================================
1020
1021
    /// The number of bits occupied by this type when packed into a usize.
1022
    ///
1023
    /// This must be provided to determine the number of bits into which to pack
1024
    /// the type.
1025
    const LEN: usize;
1026
    /// The type packed on the less significant side of this type.
1027
    ///
1028
    /// If this type is packed into the least significant bit of a usize, this
1029
    /// should be `()`, which occupies no bytes.
1030
    ///
1031
    /// This is used to calculate the shift amount for packing this value.
1032
    type Prev: Pack<C>;
1033
1034
    // ====== calculated automatically ========================================
1035
1036
    /// A number consisting of `Self::LEN` 1 bits, starting at the least
1037
    /// significant bit.
1038
    ///
1039
    /// This is the higest value this type can represent. This number is shifted
1040
    /// left by `Self::SHIFT` bits to calculate this type's `MASK`.
1041
    ///
1042
    /// This is computed automatically based on `Self::LEN`.
1043
    const BITS: usize = {
1044
        let shift = 1 << (Self::LEN - 1);
1045
        shift | (shift - 1)
1046
    };
1047
    /// The number of bits to shift a number to pack it into a usize with other
1048
    /// values.
1049
    ///
1050
    /// This is caculated automatically based on the `LEN` and `SHIFT` constants
1051
    /// of the previous value.
1052
    const SHIFT: usize = Self::Prev::SHIFT + Self::Prev::LEN;
1053
1054
    /// The mask to extract only this type from a packed `usize`.
1055
    ///
1056
    /// This is calculated by shifting `Self::BITS` left by `Self::SHIFT`.
1057
    const MASK: usize = Self::BITS << Self::SHIFT;
1058
1059
    fn as_usize(&self) -> usize;
1060
    fn from_usize(val: usize) -> Self;
1061
1062
    #[inline(always)]
1063
0
    fn pack(&self, to: usize) -> usize {
1064
0
        let value = self.as_usize();
1065
0
        debug_assert!(value <= Self::BITS);
1066
1067
0
        (to & !Self::MASK) | (value << Self::SHIFT)
1068
0
    }
Unexecuted instantiation: <sharded_slab::tid::Tid<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::pack
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::pack
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::pack
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::pack
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::pack
Unexecuted instantiation: <_ as sharded_slab::Pack<_>>::pack
1069
1070
    #[inline(always)]
1071
0
    fn from_packed(from: usize) -> Self {
1072
0
        let value = (from & Self::MASK) >> Self::SHIFT;
1073
0
        debug_assert!(value <= Self::BITS);
1074
0
        Self::from_usize(value)
1075
0
    }
Unexecuted instantiation: <sharded_slab::page::Addr as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <sharded_slab::page::slot::Generation as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <sharded_slab::tid::Tid<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <sharded_slab::page::slot::LifecycleGen<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <sharded_slab::page::slot::Lifecycle<sharded_slab::cfg::DefaultConfig> as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <sharded_slab::page::slot::RefCount as sharded_slab::Pack<sharded_slab::cfg::DefaultConfig>>::from_packed
Unexecuted instantiation: <_ as sharded_slab::Pack<_>>::from_packed
1076
}
1077
1078
impl<C: cfg::Config> Pack<C> for () {
1079
    const BITS: usize = 0;
1080
    const LEN: usize = 0;
1081
    const SHIFT: usize = 0;
1082
    const MASK: usize = 0;
1083
1084
    type Prev = ();
1085
1086
0
    fn as_usize(&self) -> usize {
1087
0
        unreachable!()
1088
    }
1089
0
    fn from_usize(_val: usize) -> Self {
1090
0
        unreachable!()
1091
    }
1092
1093
0
    fn pack(&self, _to: usize) -> usize {
1094
0
        unreachable!()
1095
    }
1096
1097
0
    fn from_packed(_from: usize) -> Self {
1098
0
        unreachable!()
1099
    }
1100
}
1101
1102
#[cfg(test)]
1103
pub(crate) use self::tests::util as test_util;
1104
1105
#[cfg(test)]
1106
mod tests;