sharded_slab/
pool.rs

1//! A lock-free concurrent object pool.
2//!
3//! See the [`Pool` type's documentation][pool] for details on the object pool API and how
4//! it differs from the [`Slab`] API.
5//!
6//! [pool]: ../struct.Pool.html
7//! [`Slab`]: ../struct.Slab.html
8use crate::{
9    cfg::{self, CfgPrivate, DefaultConfig},
10    clear::Clear,
11    page, shard,
12    tid::Tid,
13    Pack, Shard,
14};
15
16use std::{fmt, marker::PhantomData, sync::Arc};
17
18/// A lock-free concurrent object pool.
19///
20/// Slabs provide pre-allocated storage for many instances of a single type. But, when working with
21/// heap allocated objects, the advantages of a slab are lost, as the memory allocated for the
22/// object is freed when the object is removed from the slab. With a pool, we can instead reuse
23/// this memory for objects being added to the pool in the future, therefore reducing memory
24/// fragmentation and avoiding additional allocations.
25///
26/// This type implements a lock-free concurrent pool, indexed by `usize`s. The items stored in this
27/// type need to implement [`Clear`] and `Default`.
28///
29/// The `Pool` type shares similar semantics to [`Slab`] when it comes to sharing across threads
30/// and storing mutable shared data. The biggest difference is there are no [`Slab::insert`] and
31/// [`Slab::take`] analouges for the `Pool` type. Instead new items are added to the pool by using
32/// the [`Pool::create`] method, and marked for clearing by the [`Pool::clear`] method.
33///
34/// # Examples
35///
36/// Add an entry to the pool, returning an index:
37/// ```
38/// # use sharded_slab::Pool;
39/// let pool: Pool<String> = Pool::new();
40///
41/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
42/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
43/// ```
44///
45/// Create a new pooled item, returning a guard that allows mutable access:
46/// ```
47/// # use sharded_slab::Pool;
48/// let pool: Pool<String> = Pool::new();
49///
50/// let mut guard = pool.create().unwrap();
51/// let key = guard.key();
52/// guard.push_str("hello world");
53///
54/// drop(guard); // release the guard, allowing immutable access.
55/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
56/// ```
57///
58/// Pool entries can be cleared by calling [`Pool::clear`]. This marks the entry to
59/// be cleared when the guards referencing to it are dropped.
60/// ```
61/// # use sharded_slab::Pool;
62/// let pool: Pool<String> = Pool::new();
63///
64/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
65///
66/// // Mark this entry to be cleared.
67/// pool.clear(key);
68///
69/// // The cleared entry is no longer available in the pool
70/// assert!(pool.get(key).is_none());
71/// ```
72/// # Configuration
73///
74/// Both `Pool` and [`Slab`] share the same configuration mechanism. See [crate level documentation][config-doc]
75/// for more details.
76///
77/// [`Slab::take`]: crate::Slab::take
78/// [`Slab::insert`]: crate::Slab::insert
79/// [`Pool::create`]: Pool::create
80/// [`Pool::clear`]: Pool::clear
81/// [config-doc]: crate#configuration
82/// [`Clear`]: crate::Clear
83/// [`Slab`]: crate::Slab
84pub struct Pool<T, C = DefaultConfig>
85where
86    T: Clear + Default,
87    C: cfg::Config,
88{
89    shards: shard::Array<T, C>,
90    _cfg: PhantomData<C>,
91}
92
93/// A guard that allows access to an object in a pool.
94///
95/// While the guard exists, it indicates to the pool that the item the guard references is
96/// currently being accessed. If the item is removed from the pool while the guard exists, the
97/// removal will be deferred until all guards are dropped.
98pub struct Ref<'a, T, C = DefaultConfig>
99where
100    T: Clear + Default,
101    C: cfg::Config,
102{
103    inner: page::slot::Guard<T, C>,
104    shard: &'a Shard<T, C>,
105    key: usize,
106}
107
108/// A guard that allows exclusive mutable access to an object in a pool.
109///
110/// While the guard exists, it indicates to the pool that the item the guard
111/// references is currently being accessed. If the item is removed from the pool
112/// while a guard exists, the removal will be deferred until the guard is
113/// dropped. The slot cannot be accessed by other threads while it is accessed
114/// mutably.
115pub struct RefMut<'a, T, C = DefaultConfig>
116where
117    T: Clear + Default,
118    C: cfg::Config,
119{
120    inner: page::slot::InitGuard<T, C>,
121    shard: &'a Shard<T, C>,
122    key: usize,
123}
124
125/// An owned guard that allows shared immutable access to an object in a pool.
126///
127/// While the guard exists, it indicates to the pool that the item the guard references is
128/// currently being accessed. If the item is removed from the pool while the guard exists, the
129/// removal will be deferred until all guards are dropped.
130///
131/// Unlike [`Ref`], which borrows the pool, an `OwnedRef` clones the `Arc`
132/// around the pool. Therefore, it keeps the pool from being dropped until all
133/// such guards have been dropped. This means that an `OwnedRef` may be held for
134/// an arbitrary lifetime.
135///
136///
137/// # Examples
138///
139/// ```
140/// # use sharded_slab::Pool;
141/// use std::sync::Arc;
142///
143/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
144/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
145///
146/// // Look up the created `Key`, returning an `OwnedRef`.
147/// let value = pool.clone().get_owned(key).unwrap();
148///
149/// // Now, the original `Arc` clone of the pool may be dropped, but the
150/// // returned `OwnedRef` can still access the value.
151/// assert_eq!(value, String::from("hello world"));
152/// ```
153///
154/// Unlike [`Ref`], an `OwnedRef` may be stored in a struct which must live
155/// for the `'static` lifetime:
156///
157/// ```
158/// # use sharded_slab::Pool;
159/// use sharded_slab::pool::OwnedRef;
160/// use std::sync::Arc;
161///
162/// pub struct MyStruct {
163///     pool_ref: OwnedRef<String>,
164///     // ... other fields ...
165/// }
166///
167/// // Suppose this is some arbitrary function which requires a value that
168/// // lives for the 'static lifetime...
169/// fn function_requiring_static<T: 'static>(t: &T) {
170///     // ... do something extremely important and interesting ...
171/// }
172///
173/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
174/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
175///
176/// // Look up the created `Key`, returning an `OwnedRef`.
177/// let pool_ref = pool.clone().get_owned(key).unwrap();
178/// let my_struct = MyStruct {
179///     pool_ref,
180///     // ...
181/// };
182///
183/// // We can use `my_struct` anywhere where it is required to have the
184/// // `'static` lifetime:
185/// function_requiring_static(&my_struct);
186/// ```
187///
188/// `OwnedRef`s may be sent between threads:
189///
190/// ```
191/// # use sharded_slab::Pool;
192/// use std::{thread, sync::Arc};
193///
194/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
195/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
196///
197/// // Look up the created `Key`, returning an `OwnedRef`.
198/// let value = pool.clone().get_owned(key).unwrap();
199///
200/// thread::spawn(move || {
201///     assert_eq!(value, String::from("hello world"));
202///     // ...
203/// }).join().unwrap();
204/// ```
205///
206/// [`Ref`]: crate::pool::Ref
207pub struct OwnedRef<T, C = DefaultConfig>
208where
209    T: Clear + Default,
210    C: cfg::Config,
211{
212    inner: page::slot::Guard<T, C>,
213    pool: Arc<Pool<T, C>>,
214    key: usize,
215}
216
217/// An owned guard that allows exclusive, mutable access to an object in a pool.
218///
219/// An `OwnedRefMut<T>` functions more or less identically to an owned
220/// `Box<T>`: it can be passed to functions, stored in structure fields, and
221/// borrowed mutably or immutably, and can be owned for arbitrary lifetimes.
222/// The difference is that, unlike a `Box<T>`, the memory allocation for the
223/// `T` lives in the `Pool`; when an `OwnedRefMut` is created, it may reuse
224/// memory that was allocated for a previous pooled object that has been
225/// cleared. Additionally, the `OwnedRefMut` may be [downgraded] to an
226/// [`OwnedRef`] which may be shared freely, essentially turning the `Box`
227/// into an `Arc`.
228///
229/// This is returned by [`Pool::create_owned`].
230///
231/// While the guard exists, it indicates to the pool that the item the guard
232/// references is currently being accessed. If the item is removed from the pool
233/// while the guard exists, theremoval will be deferred until all guards are
234/// dropped.
235///
236/// Unlike [`RefMut`], which borrows the pool, an `OwnedRefMut` clones the `Arc`
237/// around the pool. Therefore, it keeps the pool from being dropped until all
238/// such guards have been dropped. This means that an `OwnedRefMut` may be held for
239/// an arbitrary lifetime.
240///
241/// # Examples
242///
243/// ```rust
244/// # use sharded_slab::Pool;
245/// # use std::thread;
246/// use std::sync::Arc;
247///
248/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
249///
250/// // Create a new pooled item, returning an owned guard that allows mutable
251/// // access to the new item.
252/// let mut item = pool.clone().create_owned().unwrap();
253/// // Return a key that allows indexing the created item once the guard
254/// // has been dropped.
255/// let key = item.key();
256///
257/// // Mutate the item.
258/// item.push_str("Hello");
259/// // Drop the guard, releasing mutable access to the new item.
260/// drop(item);
261///
262/// /// Other threads may now (immutably) access the item using the returned key.
263/// thread::spawn(move || {
264///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
265/// }).join().unwrap();
266/// ```
267///
268/// ```rust
269/// # use sharded_slab::Pool;
270/// use std::sync::Arc;
271///
272/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
273///
274/// // Create a new item, returning an owned, mutable guard.
275/// let mut value = pool.clone().create_owned().unwrap();
276///
277/// // Now, the original `Arc` clone of the pool may be dropped, but the
278/// // returned `OwnedRefMut` can still access the value.
279/// drop(pool);
280///
281/// value.push_str("hello world");
282/// assert_eq!(value, String::from("hello world"));
283/// ```
284///
285/// Unlike [`RefMut`], an `OwnedRefMut` may be stored in a struct which must live
286/// for the `'static` lifetime:
287///
288/// ```
289/// # use sharded_slab::Pool;
290/// use sharded_slab::pool::OwnedRefMut;
291/// use std::sync::Arc;
292///
293/// pub struct MyStruct {
294///     pool_ref: OwnedRefMut<String>,
295///     // ... other fields ...
296/// }
297///
298/// // Suppose this is some arbitrary function which requires a value that
299/// // lives for the 'static lifetime...
300/// fn function_requiring_static<T: 'static>(t: &T) {
301///     // ... do something extremely important and interesting ...
302/// }
303///
304/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
305///
306/// // Create a new item, returning a mutable owned reference.
307/// let pool_ref = pool.clone().create_owned().unwrap();
308///
309/// let my_struct = MyStruct {
310///     pool_ref,
311///     // ...
312/// };
313///
314/// // We can use `my_struct` anywhere where it is required to have the
315/// // `'static` lifetime:
316/// function_requiring_static(&my_struct);
317/// ```
318///
319/// `OwnedRefMut`s may be sent between threads:
320///
321/// ```
322/// # use sharded_slab::Pool;
323/// use std::{thread, sync::Arc};
324///
325/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
326///
327/// let mut value = pool.clone().create_owned().unwrap();
328/// let key = value.key();
329///
330/// thread::spawn(move || {
331///     value.push_str("hello world");
332///     // ...
333/// }).join().unwrap();
334///
335/// // Once the `OwnedRefMut` has been dropped by the other thread, we may
336/// // now access the value immutably on this thread.
337///
338/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
339/// ```
340///
341/// Downgrading from a mutable to an immutable reference:
342///
343/// ```
344/// # use sharded_slab::Pool;
345/// use std::{thread, sync::Arc};
346///
347/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
348///
349/// let mut value = pool.clone().create_owned().unwrap();
350/// let key = value.key();
351/// value.push_str("hello world");
352///
353/// // Downgrade the mutable owned ref to an immutable owned ref.
354/// let value = value.downgrade();
355///
356/// // Once the `OwnedRefMut` has been downgraded, other threads may
357/// // immutably access the pooled value:
358/// thread::spawn(move || {
359///     assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
360/// }).join().unwrap();
361///
362/// // This thread can still access the pooled value through the
363/// // immutable owned ref:
364/// assert_eq!(value, String::from("hello world"));
365/// ```
366///
367/// [`Pool::create_owned`]: crate::Pool::create_owned
368/// [`RefMut`]: crate::pool::RefMut
369/// [`OwnedRefMut`]: crate::pool::OwnedRefMut
370/// [downgraded]: crate::pool::OwnedRefMut::downgrade
371pub struct OwnedRefMut<T, C = DefaultConfig>
372where
373    T: Clear + Default,
374    C: cfg::Config,
375{
376    inner: page::slot::InitGuard<T, C>,
377    pool: Arc<Pool<T, C>>,
378    key: usize,
379}
380
381impl<T> Pool<T>
382where
383    T: Clear + Default,
384{
385    /// Returns a new `Pool` with the default configuration parameters.
386    pub fn new() -> Self {
387        Self::new_with_config()
388    }
389
390    /// Returns a new `Pool` with the provided configuration parameters.
391    pub fn new_with_config<C: cfg::Config>() -> Pool<T, C> {
392        C::validate();
393        Pool {
394            shards: shard::Array::new(),
395            _cfg: PhantomData,
396        }
397    }
398}
399
400impl<T, C> Pool<T, C>
401where
402    T: Clear + Default,
403    C: cfg::Config,
404{
405    /// The number of bits in each index which are used by the pool.
406    ///
407    /// If other data is packed into the `usize` indices returned by
408    /// [`Pool::create`], user code is free to use any bits higher than the
409    /// `USED_BITS`-th bit freely.
410    ///
411    /// This is determined by the [`Config`] type that configures the pool's
412    /// parameters. By default, all bits are used; this can be changed by
413    /// overriding the [`Config::RESERVED_BITS`][res] constant.
414    ///
415    /// [`Config`]: trait.Config.html
416    /// [res]: trait.Config.html#associatedconstant.RESERVED_BITS
417    /// [`Slab::insert`]: struct.Slab.html#method.insert
418    pub const USED_BITS: usize = C::USED_BITS;
419
420    /// Creates a new object in the pool, returning an [`RefMut`] guard that
421    /// may be used to mutate the new object.
422    ///
423    /// If this function returns `None`, then the shard for the current thread is full and no items
424    /// can be added until some are removed, or the maximum number of shards has been reached.
425    ///
426    /// # Examples
427    /// ```rust
428    /// # use sharded_slab::Pool;
429    /// # use std::thread;
430    /// let pool: Pool<String> = Pool::new();
431    ///
432    /// // Create a new pooled item, returning a guard that allows mutable
433    /// // access to the new item.
434    /// let mut item = pool.create().unwrap();
435    /// // Return a key that allows indexing the created item once the guard
436    /// // has been dropped.
437    /// let key = item.key();
438    ///
439    /// // Mutate the item.
440    /// item.push_str("Hello");
441    /// // Drop the guard, releasing mutable access to the new item.
442    /// drop(item);
443    ///
444    /// /// Other threads may now (immutably) access the item using the returned key.
445    /// thread::spawn(move || {
446    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
447    /// }).join().unwrap();
448    /// ```
449    ///
450    /// [`RefMut`]: crate::pool::RefMut
451    pub fn create(&self) -> Option<RefMut<'_, T, C>> {
452        let (tid, shard) = self.shards.current();
453        test_println!("pool: create {:?}", tid);
454        let (key, inner) = shard.init_with(|idx, slot| {
455            let guard = slot.init()?;
456            let gen = guard.generation();
457            Some((gen.pack(idx), guard))
458        })?;
459        Some(RefMut {
460            inner,
461            key: tid.pack(key),
462            shard,
463        })
464    }
465
466    /// Creates a new object in the pool, returning an [`OwnedRefMut`] guard that
467    /// may be used to mutate the new object.
468    ///
469    /// If this function returns `None`, then the shard for the current thread
470    /// is full and no items can be added until some are removed, or the maximum
471    /// number of shards has been reached.
472    ///
473    /// Unlike [`create`], which borrows the pool, this method _clones_ the `Arc`
474    /// around the pool if a value exists for the given key. This means that the
475    /// returned [`OwnedRefMut`] can be held for an arbitrary lifetime. However,
476    /// this method requires that the pool itself be wrapped in an `Arc`.
477    ///
478    /// An `OwnedRefMut<T>` functions more or less identically to an owned
479    /// `Box<T>`: it can be passed to functions, stored in structure fields, and
480    /// borrowed mutably or immutably, and can be owned for arbitrary lifetimes.
481    /// The difference is that, unlike a `Box<T>`, the memory allocation for the
482    /// `T` lives in the `Pool`; when an `OwnedRefMut` is created, it may reuse
483    /// memory that was allocated for a previous pooled object that has been
484    /// cleared. Additionally, the `OwnedRefMut` may be [downgraded] to an
485    /// [`OwnedRef`] which may be shared freely, essentially turning the `Box`
486    /// into an `Arc`.
487    ///
488    /// # Examples
489    ///
490    /// ```rust
491    /// # use sharded_slab::Pool;
492    /// # use std::thread;
493    /// use std::sync::Arc;
494    ///
495    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
496    ///
497    /// // Create a new pooled item, returning an owned guard that allows mutable
498    /// // access to the new item.
499    /// let mut item = pool.clone().create_owned().unwrap();
500    /// // Return a key that allows indexing the created item once the guard
501    /// // has been dropped.
502    /// let key = item.key();
503    ///
504    /// // Mutate the item.
505    /// item.push_str("Hello");
506    /// // Drop the guard, releasing mutable access to the new item.
507    /// drop(item);
508    ///
509    /// /// Other threads may now (immutably) access the item using the returned key.
510    /// thread::spawn(move || {
511    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
512    /// }).join().unwrap();
513    /// ```
514    ///
515    /// ```rust
516    /// # use sharded_slab::Pool;
517    /// use std::sync::Arc;
518    ///
519    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
520    ///
521    /// // Create a new item, returning an owned, mutable guard.
522    /// let mut value = pool.clone().create_owned().unwrap();
523    ///
524    /// // Now, the original `Arc` clone of the pool may be dropped, but the
525    /// // returned `OwnedRefMut` can still access the value.
526    /// drop(pool);
527    ///
528    /// value.push_str("hello world");
529    /// assert_eq!(value, String::from("hello world"));
530    /// ```
531    ///
532    /// Unlike [`RefMut`], an `OwnedRefMut` may be stored in a struct which must live
533    /// for the `'static` lifetime:
534    ///
535    /// ```
536    /// # use sharded_slab::Pool;
537    /// use sharded_slab::pool::OwnedRefMut;
538    /// use std::sync::Arc;
539    ///
540    /// pub struct MyStruct {
541    ///     pool_ref: OwnedRefMut<String>,
542    ///     // ... other fields ...
543    /// }
544    ///
545    /// // Suppose this is some arbitrary function which requires a value that
546    /// // lives for the 'static lifetime...
547    /// fn function_requiring_static<T: 'static>(t: &T) {
548    ///     // ... do something extremely important and interesting ...
549    /// }
550    ///
551    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
552    ///
553    /// // Create a new item, returning a mutable owned reference.
554    /// let pool_ref = pool.clone().create_owned().unwrap();
555    ///
556    /// let my_struct = MyStruct {
557    ///     pool_ref,
558    ///     // ...
559    /// };
560    ///
561    /// // We can use `my_struct` anywhere where it is required to have the
562    /// // `'static` lifetime:
563    /// function_requiring_static(&my_struct);
564    /// ```
565    ///
566    /// `OwnedRefMut`s may be sent between threads:
567    ///
568    /// ```
569    /// # use sharded_slab::Pool;
570    /// use std::{thread, sync::Arc};
571    ///
572    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
573    ///
574    /// let mut value = pool.clone().create_owned().unwrap();
575    /// let key = value.key();
576    ///
577    /// thread::spawn(move || {
578    ///     value.push_str("hello world");
579    ///     // ...
580    /// }).join().unwrap();
581    ///
582    /// // Once the `OwnedRefMut` has been dropped by the other thread, we may
583    /// // now access the value immutably on this thread.
584    ///
585    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
586    /// ```
587    ///
588    /// Downgrading from a mutable to an immutable reference:
589    ///
590    /// ```
591    /// # use sharded_slab::Pool;
592    /// use std::{thread, sync::Arc};
593    ///
594    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
595    ///
596    /// let mut value = pool.clone().create_owned().unwrap();
597    /// let key = value.key();
598    /// value.push_str("hello world");
599    ///
600    /// // Downgrade the mutable owned ref to an immutable owned ref.
601    /// let value = value.downgrade();
602    ///
603    /// // Once the `OwnedRefMut` has been downgraded, other threads may
604    /// // immutably access the pooled value:
605    /// thread::spawn(move || {
606    ///     assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
607    /// }).join().unwrap();
608    ///
609    /// // This thread can still access the pooled value through the
610    /// // immutable owned ref:
611    /// assert_eq!(value, String::from("hello world"));
612    /// ```
613    ///
614    /// [`create`]: Pool::create
615    /// [`OwnedRef`]: crate::pool::OwnedRef
616    /// [`RefMut`]: crate::pool::RefMut
617    /// [`OwnedRefMut`]: crate::pool::OwnedRefMut
618    /// [downgraded]: crate::pool::OwnedRefMut::downgrade
619    pub fn create_owned(self: Arc<Self>) -> Option<OwnedRefMut<T, C>> {
620        let (tid, shard) = self.shards.current();
621        test_println!("pool: create_owned {:?}", tid);
622        let (inner, key) = shard.init_with(|idx, slot| {
623            let inner = slot.init()?;
624            let gen = inner.generation();
625            Some((inner, tid.pack(gen.pack(idx))))
626        })?;
627        Some(OwnedRefMut {
628            inner,
629            pool: self,
630            key,
631        })
632    }
633
634    /// Creates a new object in the pool with the provided initializer,
635    /// returning a key that may be used to access the new object.
636    ///
637    /// If this function returns `None`, then the shard for the current thread is full and no items
638    /// can be added until some are removed, or the maximum number of shards has been reached.
639    ///
640    /// # Examples
641    /// ```rust
642    /// # use sharded_slab::Pool;
643    /// # use std::thread;
644    /// let pool: Pool<String> = Pool::new();
645    ///
646    /// // Create a new pooled item, returning its integer key.
647    /// let key = pool.create_with(|s| s.push_str("Hello")).unwrap();
648    ///
649    /// /// Other threads may now (immutably) access the item using the key.
650    /// thread::spawn(move || {
651    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
652    /// }).join().unwrap();
653    /// ```
654    pub fn create_with(&self, init: impl FnOnce(&mut T)) -> Option<usize> {
655        test_println!("pool: create_with");
656        let mut guard = self.create()?;
657        init(&mut guard);
658        Some(guard.key())
659    }
660
661    /// Return a borrowed reference to the value associated with the given key.
662    ///
663    /// If the pool does not contain a value for the given key, `None` is returned instead.
664    ///
665    /// # Examples
666    ///
667    /// ```rust
668    /// # use sharded_slab::Pool;
669    /// let pool: Pool<String> = Pool::new();
670    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
671    ///
672    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
673    /// assert!(pool.get(12345).is_none());
674    /// ```
675    pub fn get(&self, key: usize) -> Option<Ref<'_, T, C>> {
676        let tid = C::unpack_tid(key);
677
678        test_println!("pool: get{:?}; current={:?}", tid, Tid::<C>::current());
679        let shard = self.shards.get(tid.as_usize())?;
680        let inner = shard.with_slot(key, |slot| slot.get(C::unpack_gen(key)))?;
681        Some(Ref { inner, shard, key })
682    }
683
684    /// Return an owned reference to the value associated with the given key.
685    ///
686    /// If the pool does not contain a value for the given key, `None` is
687    /// returned instead.
688    ///
689    /// Unlike [`get`], which borrows the pool, this method _clones_ the `Arc`
690    /// around the pool if a value exists for the given key. This means that the
691    /// returned [`OwnedRef`] can be held for an arbitrary lifetime. However,
692    /// this method requires that the pool itself be wrapped in an `Arc`.
693    ///
694    /// # Examples
695    ///
696    /// ```rust
697    /// # use sharded_slab::Pool;
698    /// use std::sync::Arc;
699    ///
700    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
701    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
702    ///
703    /// // Look up the created `Key`, returning an `OwnedRef`.
704    /// let value = pool.clone().get_owned(key).unwrap();
705    ///
706    /// // Now, the original `Arc` clone of the pool may be dropped, but the
707    /// // returned `OwnedRef` can still access the value.
708    /// assert_eq!(value, String::from("hello world"));
709    /// ```
710    ///
711    /// Unlike [`Ref`], an `OwnedRef` may be stored in a struct which must live
712    /// for the `'static` lifetime:
713    ///
714    /// ```
715    /// # use sharded_slab::Pool;
716    /// use sharded_slab::pool::OwnedRef;
717    /// use std::sync::Arc;
718    ///
719    /// pub struct MyStruct {
720    ///     pool_ref: OwnedRef<String>,
721    ///     // ... other fields ...
722    /// }
723    ///
724    /// // Suppose this is some arbitrary function which requires a value that
725    /// // lives for the 'static lifetime...
726    /// fn function_requiring_static<T: 'static>(t: &T) {
727    ///     // ... do something extremely important and interesting ...
728    /// }
729    ///
730    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
731    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
732    ///
733    /// // Look up the created `Key`, returning an `OwnedRef`.
734    /// let pool_ref = pool.clone().get_owned(key).unwrap();
735    /// let my_struct = MyStruct {
736    ///     pool_ref,
737    ///     // ...
738    /// };
739    ///
740    /// // We can use `my_struct` anywhere where it is required to have the
741    /// // `'static` lifetime:
742    /// function_requiring_static(&my_struct);
743    /// ```
744    ///
745    /// `OwnedRef`s may be sent between threads:
746    ///
747    /// ```
748    /// # use sharded_slab::Pool;
749    /// use std::{thread, sync::Arc};
750    ///
751    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
752    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
753    ///
754    /// // Look up the created `Key`, returning an `OwnedRef`.
755    /// let value = pool.clone().get_owned(key).unwrap();
756    ///
757    /// thread::spawn(move || {
758    ///     assert_eq!(value, String::from("hello world"));
759    ///     // ...
760    /// }).join().unwrap();
761    /// ```
762    ///
763    /// [`get`]: Pool::get
764    /// [`OwnedRef`]: crate::pool::OwnedRef
765    /// [`Ref`]: crate::pool::Ref
766    pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedRef<T, C>> {
767        let tid = C::unpack_tid(key);
768
769        test_println!("pool: get{:?}; current={:?}", tid, Tid::<C>::current());
770        let shard = self.shards.get(tid.as_usize())?;
771        let inner = shard.with_slot(key, |slot| slot.get(C::unpack_gen(key)))?;
772        Some(OwnedRef {
773            inner,
774            pool: self.clone(),
775            key,
776        })
777    }
778
779    /// Remove the value using the storage associated with the given key from the pool, returning
780    /// `true` if the value was removed.
781    ///
782    /// This method does _not_ block the current thread until the value can be
783    /// cleared. Instead, if another thread is currently accessing that value, this marks it to be
784    /// cleared by that thread when it is done accessing that value.
785    ///
786    /// # Examples
787    ///
788    /// ```rust
789    /// # use sharded_slab::Pool;
790    /// let pool: Pool<String> = Pool::new();
791    ///
792    /// // Check out an item from the pool.
793    /// let mut item = pool.create().unwrap();
794    /// let key = item.key();
795    /// item.push_str("hello world");
796    /// drop(item);
797    ///
798    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
799    ///
800    /// pool.clear(key);
801    /// assert!(pool.get(key).is_none());
802    /// ```
803    ///
804    /// ```
805    /// # use sharded_slab::Pool;
806    /// let pool: Pool<String> = Pool::new();
807    ///
808    /// let key = pool.create_with(|item| item.push_str("Hello world!")).unwrap();
809    ///
810    /// // Clearing a key that doesn't exist in the `Pool` will return `false`
811    /// assert_eq!(pool.clear(key + 69420), false);
812    ///
813    /// // Clearing a key that does exist returns `true`
814    /// assert!(pool.clear(key));
815    ///
816    /// // Clearing a key that has previously been cleared will return `false`
817    /// assert_eq!(pool.clear(key), false);
818    /// ```
819    /// [`clear`]: #method.clear
820    pub fn clear(&self, key: usize) -> bool {
821        let tid = C::unpack_tid(key);
822
823        let shard = self.shards.get(tid.as_usize());
824        if tid.is_current() {
825            shard
826                .map(|shard| shard.mark_clear_local(key))
827                .unwrap_or(false)
828        } else {
829            shard
830                .map(|shard| shard.mark_clear_remote(key))
831                .unwrap_or(false)
832        }
833    }
834}
835
836unsafe impl<T, C> Send for Pool<T, C>
837where
838    T: Send + Clear + Default,
839    C: cfg::Config,
840{
841}
842unsafe impl<T, C> Sync for Pool<T, C>
843where
844    T: Sync + Clear + Default,
845    C: cfg::Config,
846{
847}
848
849impl<T> Default for Pool<T>
850where
851    T: Clear + Default,
852{
853    fn default() -> Self {
854        Self::new()
855    }
856}
857
858impl<T, C> fmt::Debug for Pool<T, C>
859where
860    T: fmt::Debug + Clear + Default,
861    C: cfg::Config,
862{
863    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
864        f.debug_struct("Pool")
865            .field("shards", &self.shards)
866            .field("config", &C::debug())
867            .finish()
868    }
869}
870
871// === impl Ref ===
872
873impl<'a, T, C> Ref<'a, T, C>
874where
875    T: Clear + Default,
876    C: cfg::Config,
877{
878    /// Returns the key used to access this guard
879    pub fn key(&self) -> usize {
880        self.key
881    }
882
883    #[inline]
884    fn value(&self) -> &T {
885        unsafe {
886            // Safety: calling `slot::Guard::value` is unsafe, since the `Guard`
887            // value contains a pointer to the slot that may outlive the slab
888            // containing that slot. Here, the `Ref` has a borrowed reference to
889            // the shard containing that slot, which ensures that the slot will
890            // not be dropped while this `Guard` exists.
891            self.inner.value()
892        }
893    }
894}
895
896impl<'a, T, C> std::ops::Deref for Ref<'a, T, C>
897where
898    T: Clear + Default,
899    C: cfg::Config,
900{
901    type Target = T;
902
903    fn deref(&self) -> &Self::Target {
904        self.value()
905    }
906}
907
908impl<'a, T, C> Drop for Ref<'a, T, C>
909where
910    T: Clear + Default,
911    C: cfg::Config,
912{
913    fn drop(&mut self) {
914        test_println!("drop Ref: try clearing data");
915        let should_clear = unsafe {
916            // Safety: calling `slot::Guard::release` is unsafe, since the
917            // `Guard` value contains a pointer to the slot that may outlive the
918            // slab containing that slot. Here, the `Ref` guard owns a
919            // borrowed reference to the shard containing that slot, which
920            // ensures that the slot will not be dropped while this `Ref`
921            // exists.
922            self.inner.release()
923        };
924        if should_clear {
925            self.shard.clear_after_release(self.key);
926        }
927    }
928}
929
930impl<'a, T, C> fmt::Debug for Ref<'a, T, C>
931where
932    T: fmt::Debug + Clear + Default,
933    C: cfg::Config,
934{
935    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
936        fmt::Debug::fmt(self.value(), f)
937    }
938}
939
940impl<'a, T, C> PartialEq<T> for Ref<'a, T, C>
941where
942    T: PartialEq<T> + Clear + Default,
943    C: cfg::Config,
944{
945    fn eq(&self, other: &T) -> bool {
946        *self.value() == *other
947    }
948}
949
950// === impl GuardMut ===
951
952impl<'a, T, C: cfg::Config> RefMut<'a, T, C>
953where
954    T: Clear + Default,
955    C: cfg::Config,
956{
957    /// Returns the key used to access the guard.
958    pub fn key(&self) -> usize {
959        self.key
960    }
961
962    /// Downgrades the mutable guard to an immutable guard, allowing access to
963    /// the pooled value from other threads.
964    ///
965    /// ## Examples
966    ///
967    /// ```
968    /// # use sharded_slab::Pool;
969    /// # use std::{sync::Arc, thread};
970    /// let pool = Arc::new(Pool::<String>::new());
971    ///
972    /// let mut guard_mut = pool.clone().create_owned().unwrap();
973    /// let key = guard_mut.key();
974    /// guard_mut.push_str("Hello");
975    ///
976    /// // The pooled string is currently borrowed mutably, so other threads
977    /// // may not access it.
978    /// let pool2 = pool.clone();
979    /// thread::spawn(move || {
980    ///     assert!(pool2.get(key).is_none())
981    /// }).join().unwrap();
982    ///
983    /// // Downgrade the guard to an immutable reference.
984    /// let guard = guard_mut.downgrade();
985    ///
986    /// // Now, other threads may also access the pooled value.
987    /// let pool2 = pool.clone();
988    /// thread::spawn(move || {
989    ///     let guard = pool2.get(key)
990    ///         .expect("the item may now be referenced by other threads");
991    ///     assert_eq!(guard, String::from("Hello"));
992    /// }).join().unwrap();
993    ///
994    /// // We can still access the value immutably through the downgraded guard.
995    /// assert_eq!(guard, String::from("Hello"));
996    /// ```
997    pub fn downgrade(mut self) -> Ref<'a, T, C> {
998        let inner = unsafe { self.inner.downgrade() };
999        Ref {
1000            inner,
1001            shard: self.shard,
1002            key: self.key,
1003        }
1004    }
1005
1006    #[inline]
1007    fn value(&self) -> &T {
1008        unsafe {
1009            // Safety: we are holding a reference to the shard which keeps the
1010            // pointed slot alive. The returned reference will not outlive
1011            // `self`.
1012            self.inner.value()
1013        }
1014    }
1015}
1016
1017impl<'a, T, C: cfg::Config> std::ops::Deref for RefMut<'a, T, C>
1018where
1019    T: Clear + Default,
1020    C: cfg::Config,
1021{
1022    type Target = T;
1023
1024    fn deref(&self) -> &Self::Target {
1025        self.value()
1026    }
1027}
1028
1029impl<'a, T, C> std::ops::DerefMut for RefMut<'a, T, C>
1030where
1031    T: Clear + Default,
1032    C: cfg::Config,
1033{
1034    fn deref_mut(&mut self) -> &mut Self::Target {
1035        unsafe {
1036            // Safety: we are holding a reference to the shard which keeps the
1037            // pointed slot alive. The returned reference will not outlive `self`.
1038            self.inner.value_mut()
1039        }
1040    }
1041}
1042
1043impl<'a, T, C> Drop for RefMut<'a, T, C>
1044where
1045    T: Clear + Default,
1046    C: cfg::Config,
1047{
1048    fn drop(&mut self) {
1049        test_println!(" -> drop RefMut: try clearing data");
1050        let should_clear = unsafe {
1051            // Safety: we are holding a reference to the shard which keeps the
1052            // pointed slot alive. The returned reference will not outlive `self`.
1053            self.inner.release()
1054        };
1055        if should_clear {
1056            self.shard.clear_after_release(self.key);
1057        }
1058    }
1059}
1060
1061impl<'a, T, C> fmt::Debug for RefMut<'a, T, C>
1062where
1063    T: fmt::Debug + Clear + Default,
1064    C: cfg::Config,
1065{
1066    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067        fmt::Debug::fmt(self.value(), f)
1068    }
1069}
1070
1071impl<'a, T, C> PartialEq<T> for RefMut<'a, T, C>
1072where
1073    T: PartialEq<T> + Clear + Default,
1074    C: cfg::Config,
1075{
1076    fn eq(&self, other: &T) -> bool {
1077        self.value().eq(other)
1078    }
1079}
1080
1081// === impl OwnedRef ===
1082
1083impl<T, C> OwnedRef<T, C>
1084where
1085    T: Clear + Default,
1086    C: cfg::Config,
1087{
1088    /// Returns the key used to access this guard
1089    pub fn key(&self) -> usize {
1090        self.key
1091    }
1092
1093    #[inline]
1094    fn value(&self) -> &T {
1095        unsafe {
1096            // Safety: calling `slot::Guard::value` is unsafe, since the `Guard`
1097            // value contains a pointer to the slot that may outlive the slab
1098            // containing that slot. Here, the `Ref` has a borrowed reference to
1099            // the shard containing that slot, which ensures that the slot will
1100            // not be dropped while this `Guard` exists.
1101            self.inner.value()
1102        }
1103    }
1104}
1105
1106impl<T, C> std::ops::Deref for OwnedRef<T, C>
1107where
1108    T: Clear + Default,
1109    C: cfg::Config,
1110{
1111    type Target = T;
1112
1113    fn deref(&self) -> &Self::Target {
1114        self.value()
1115    }
1116}
1117
1118impl<T, C> Drop for OwnedRef<T, C>
1119where
1120    T: Clear + Default,
1121    C: cfg::Config,
1122{
1123    fn drop(&mut self) {
1124        test_println!("drop OwnedRef: try clearing data");
1125        let should_clear = unsafe {
1126            // Safety: calling `slot::Guard::release` is unsafe, since the
1127            // `Guard` value contains a pointer to the slot that may outlive the
1128            // slab containing that slot. Here, the `OwnedRef` owns an `Arc`
1129            // clone of the pool, which keeps it alive as long as the `OwnedRef`
1130            // exists.
1131            self.inner.release()
1132        };
1133        if should_clear {
1134            let shard_idx = Tid::<C>::from_packed(self.key);
1135            test_println!("-> shard={:?}", shard_idx);
1136            if let Some(shard) = self.pool.shards.get(shard_idx.as_usize()) {
1137                shard.clear_after_release(self.key);
1138            } else {
1139                test_println!("-> shard={:?} does not exist! THIS IS A BUG", shard_idx);
1140                debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedRef` to a slot on a shard that never existed!");
1141            }
1142        }
1143    }
1144}
1145
1146impl<T, C> fmt::Debug for OwnedRef<T, C>
1147where
1148    T: fmt::Debug + Clear + Default,
1149    C: cfg::Config,
1150{
1151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1152        fmt::Debug::fmt(self.value(), f)
1153    }
1154}
1155
1156impl<T, C> PartialEq<T> for OwnedRef<T, C>
1157where
1158    T: PartialEq<T> + Clear + Default,
1159    C: cfg::Config,
1160{
1161    fn eq(&self, other: &T) -> bool {
1162        *self.value() == *other
1163    }
1164}
1165
1166unsafe impl<T, C> Sync for OwnedRef<T, C>
1167where
1168    T: Sync + Clear + Default,
1169    C: cfg::Config,
1170{
1171}
1172
1173unsafe impl<T, C> Send for OwnedRef<T, C>
1174where
1175    T: Sync + Clear + Default,
1176    C: cfg::Config,
1177{
1178}
1179
1180// === impl OwnedRefMut ===
1181
1182impl<T, C> OwnedRefMut<T, C>
1183where
1184    T: Clear + Default,
1185    C: cfg::Config,
1186{
1187    /// Returns the key used to access this guard
1188    pub fn key(&self) -> usize {
1189        self.key
1190    }
1191
1192    /// Downgrades the owned mutable guard to an owned immutable guard, allowing
1193    /// access to the pooled value from other threads.
1194    ///
1195    /// ## Examples
1196    ///
1197    /// ```
1198    /// # use sharded_slab::Pool;
1199    /// # use std::{sync::Arc, thread};
1200    /// let pool = Arc::new(Pool::<String>::new());
1201    ///
1202    /// let mut guard_mut = pool.clone().create_owned().unwrap();
1203    /// let key = guard_mut.key();
1204    /// guard_mut.push_str("Hello");
1205    ///
1206    /// // The pooled string is currently borrowed mutably, so other threads
1207    /// // may not access it.
1208    /// let pool2 = pool.clone();
1209    /// thread::spawn(move || {
1210    ///     assert!(pool2.get(key).is_none())
1211    /// }).join().unwrap();
1212    ///
1213    /// // Downgrade the guard to an immutable reference.
1214    /// let guard = guard_mut.downgrade();
1215    ///
1216    /// // Now, other threads may also access the pooled value.
1217    /// let pool2 = pool.clone();
1218    /// thread::spawn(move || {
1219    ///     let guard = pool2.get(key)
1220    ///         .expect("the item may now be referenced by other threads");
1221    ///     assert_eq!(guard, String::from("Hello"));
1222    /// }).join().unwrap();
1223    ///
1224    /// // We can still access the value immutably through the downgraded guard.
1225    /// assert_eq!(guard, String::from("Hello"));
1226    /// ```
1227    pub fn downgrade(mut self) -> OwnedRef<T, C> {
1228        let inner = unsafe { self.inner.downgrade() };
1229        OwnedRef {
1230            inner,
1231            pool: self.pool.clone(),
1232            key: self.key,
1233        }
1234    }
1235
1236    fn shard(&self) -> Option<&Shard<T, C>> {
1237        let shard_idx = Tid::<C>::from_packed(self.key);
1238        test_println!("-> shard={:?}", shard_idx);
1239        self.pool.shards.get(shard_idx.as_usize())
1240    }
1241
1242    #[inline]
1243    fn value(&self) -> &T {
1244        unsafe {
1245            // Safety: calling `slot::InitGuard::value` is unsafe, since the `Guard`
1246            // value contains a pointer to the slot that may outlive the slab
1247            // containing that slot. Here, the `OwnedRefMut` has an `Arc` clone of
1248            // the shard containing that slot, which ensures that the slot will
1249            // not be dropped while this `Guard` exists.
1250            self.inner.value()
1251        }
1252    }
1253}
1254
1255impl<T, C> std::ops::Deref for OwnedRefMut<T, C>
1256where
1257    T: Clear + Default,
1258    C: cfg::Config,
1259{
1260    type Target = T;
1261
1262    fn deref(&self) -> &Self::Target {
1263        self.value()
1264    }
1265}
1266
1267impl<T, C> std::ops::DerefMut for OwnedRefMut<T, C>
1268where
1269    T: Clear + Default,
1270    C: cfg::Config,
1271{
1272    fn deref_mut(&mut self) -> &mut Self::Target {
1273        unsafe {
1274            // Safety: calling `slot::InitGuard::value_mut` is unsafe, since the
1275            // `Guard`  value contains a pointer to the slot that may outlive
1276            // the slab   containing that slot. Here, the `OwnedRefMut` has an
1277            // `Arc` clone of the shard containing that slot, which ensures that
1278            // the slot will not be dropped while this `Guard` exists.
1279            self.inner.value_mut()
1280        }
1281    }
1282}
1283
1284impl<T, C> Drop for OwnedRefMut<T, C>
1285where
1286    T: Clear + Default,
1287    C: cfg::Config,
1288{
1289    fn drop(&mut self) {
1290        test_println!("drop OwnedRefMut: try clearing data");
1291        let should_clear = unsafe {
1292            // Safety: calling `slot::Guard::release` is unsafe, since the
1293            // `Guard` value contains a pointer to the slot that may outlive the
1294            // slab containing that slot. Here, the `OwnedRefMut` owns an `Arc`
1295            // clone of the pool, which keeps it alive as long as the
1296            // `OwnedRefMut` exists.
1297            self.inner.release()
1298        };
1299        if should_clear {
1300            if let Some(shard) = self.shard() {
1301                shard.clear_after_release(self.key);
1302            } else {
1303                test_println!("-> shard does not exist! THIS IS A BUG");
1304                debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedRefMut` to a slot on a shard that never existed!");
1305            }
1306        }
1307    }
1308}
1309
1310impl<T, C> fmt::Debug for OwnedRefMut<T, C>
1311where
1312    T: fmt::Debug + Clear + Default,
1313    C: cfg::Config,
1314{
1315    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1316        fmt::Debug::fmt(self.value(), f)
1317    }
1318}
1319
1320impl<T, C> PartialEq<T> for OwnedRefMut<T, C>
1321where
1322    T: PartialEq<T> + Clear + Default,
1323    C: cfg::Config,
1324{
1325    fn eq(&self, other: &T) -> bool {
1326        *self.value() == *other
1327    }
1328}
1329
1330unsafe impl<T, C> Sync for OwnedRefMut<T, C>
1331where
1332    T: Sync + Clear + Default,
1333    C: cfg::Config,
1334{
1335}
1336
1337unsafe impl<T, C> Send for OwnedRefMut<T, C>
1338where
1339    T: Sync + Clear + Default,
1340    C: cfg::Config,
1341{
1342}