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}
1343