Skip to main content

pool_mod/
object.rs

1//! The [`Pooled`] guard returned by [`Pool::get`](crate::Pool::get).
2
3use std::mem::ManuallyDrop;
4use std::ops::{Deref, DerefMut};
5use std::sync::Arc;
6use std::time::Instant;
7
8use crate::manager::Manager;
9use crate::pool::PoolInner;
10
11/// A borrowed resource that returns itself to the pool when dropped.
12///
13/// Obtained from [`Pool::get`](crate::Pool::get) and
14/// [`Pool::get_timeout`](crate::Pool::get_timeout). A `Pooled<M>` deref-coerces
15/// to the underlying resource, so it can be used anywhere a `&M::Resource` or
16/// `&mut M::Resource` is expected. When the guard goes out of scope the resource
17/// is recycled (via [`Manager::recycle`](crate::Manager::recycle)) and returned
18/// to the idle set — there is no `release` call to remember, and no way to leak a
19/// resource by forgetting one.
20///
21/// If recycling fails, or the pool has been closed, the resource is dropped
22/// instead of pooled and its slot is freed for a replacement.
23///
24/// The guard is `Send` whenever the resource is, so it may be held across
25/// `.await` points in async code.
26///
27/// # Examples
28///
29/// ```
30/// use pool_mod::{Manager, Pool};
31/// use std::convert::Infallible;
32///
33/// struct Counters;
34/// impl Manager for Counters {
35///     type Resource = u64;
36///     type Error = Infallible;
37///     fn create(&self) -> Result<u64, Infallible> { Ok(0) }
38///     fn recycle(&self, _r: &mut u64) -> Result<(), Infallible> { Ok(()) }
39/// }
40///
41/// let pool = Pool::builder(Counters).max_size(2).build()
42///     .expect("configuration is valid");
43/// {
44///     let mut n = pool.get().expect("a resource is available");
45///     *n += 1; // DerefMut to the pooled u64
46///     assert_eq!(*n, 1);
47/// } // `n` is recycled and returned to the pool here
48/// assert_eq!(pool.status().idle, 1);
49/// ```
50#[must_use = "dropping the guard immediately returns the resource to the pool"]
51pub struct Pooled<M: Manager> {
52    inner: Arc<PoolInner<M>>,
53    resource: ManuallyDrop<M::Resource>,
54    created_at: Instant,
55}
56
57impl<M: Manager> Pooled<M> {
58    pub(crate) fn new(
59        inner: Arc<PoolInner<M>>,
60        resource: M::Resource,
61        created_at: Instant,
62    ) -> Self {
63        Pooled {
64            inner,
65            resource: ManuallyDrop::new(resource),
66            created_at,
67        }
68    }
69}
70
71impl<M: Manager> Deref for Pooled<M> {
72    type Target = M::Resource;
73
74    fn deref(&self) -> &M::Resource {
75        &self.resource
76    }
77}
78
79impl<M: Manager> DerefMut for Pooled<M> {
80    fn deref_mut(&mut self) -> &mut M::Resource {
81        &mut self.resource
82    }
83}
84
85impl<M: Manager> Drop for Pooled<M> {
86    fn drop(&mut self) {
87        // SAFETY: `resource` is taken exactly once — here, as the guard is
88        // destroyed — and is never accessed again afterwards. `ManuallyDrop`
89        // suppressed its automatic destructor, so this is the sole owning move
90        // and no double drop can occur.
91        let resource = unsafe { ManuallyDrop::take(&mut self.resource) };
92        self.inner.checkin(resource, self.created_at);
93    }
94}