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}