deadpool/managed/
object.rs

1use std::{
2    fmt,
3    ops::{Deref, DerefMut},
4};
5
6use crate::managed::{Manager, Metrics, Pool, WeakPool};
7
8/// Wrapper around the actual pooled object which implements [`Deref`],
9/// [`DerefMut`] and [`Drop`] traits.
10///
11/// Use this object just as if it was of type `T` and upon leaving a scope the
12/// [`Drop::drop()`] will take care of returning it to the pool.
13#[must_use]
14pub struct Object<M: Manager> {
15    /// The actual object
16    pub(crate) inner: Option<ObjectInner<M>>,
17
18    /// Pool to return the pooled object to.
19    pub(crate) pool: WeakPool<M>,
20}
21
22impl<M> fmt::Debug for Object<M>
23where
24    M: fmt::Debug + Manager,
25    M::Type: fmt::Debug,
26{
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        f.debug_struct("Object")
29            .field("inner", &self.inner)
30            .finish()
31    }
32}
33
34#[derive(Debug)]
35pub(crate) struct ObjectInner<M: Manager> {
36    /// Actual pooled object.
37    pub obj: M::Type,
38
39    /// The ID of this object. IDs are assigned in increasing order and
40    /// generally reflect the creation order of objects.
41    ///
42    /// This can be used to discard objects after a configuration change
43    /// or simply identify an objects for debugging purposes.
44    pub id: usize,
45
46    /// Object metrics.
47    pub metrics: Metrics,
48}
49
50impl<M: Manager> Object<M> {
51    /// Takes this [`Object`] from its [`Pool`] permanently. This reduces the
52    /// size of the [`Pool`].
53    #[must_use]
54    pub fn take(mut this: Self) -> M::Type {
55        let mut inner = this.inner.take().unwrap().obj;
56        if let Some(pool) = Object::pool(&this) {
57            pool.inner.detach_object(&mut inner)
58        }
59        inner
60    }
61
62    /// Returns the unique ID of this object.
63    ///
64    /// Object IDs are strictly monotonically increasing — each new object
65    /// receives an ID greater than that of the previously created object.
66    /// However, IDs are not guaranteed to be consecutive; gaps may exist.
67    pub fn id(this: &Self) -> ObjectId {
68        ObjectId(this.inner.as_ref().unwrap().id)
69    }
70
71    /// Get object statistics
72    pub fn metrics(this: &Self) -> &Metrics {
73        &this.inner.as_ref().unwrap().metrics
74    }
75
76    /// Returns the [`Pool`] this [`Object`] belongs to.
77    ///
78    /// Since [`Object`]s only hold a [`std::sync::Weak`] reference to the
79    /// [`Pool`] they come from, this can fail and return [`None`] instead.
80    pub fn pool(this: &Self) -> Option<Pool<M>> {
81        this.pool.upgrade()
82    }
83}
84
85impl<M: Manager> Drop for Object<M> {
86    fn drop(&mut self) {
87        if let Some(inner) = self.inner.take() {
88            if let Some(pool) = self.pool.upgrade() {
89                pool.inner.return_object(inner)
90            }
91        }
92    }
93}
94
95impl<M: Manager> Deref for Object<M> {
96    type Target = M::Type;
97    fn deref(&self) -> &M::Type {
98        &self.inner.as_ref().unwrap().obj
99    }
100}
101
102impl<M: Manager> DerefMut for Object<M> {
103    fn deref_mut(&mut self) -> &mut Self::Target {
104        &mut self.inner.as_mut().unwrap().obj
105    }
106}
107
108impl<M: Manager> AsRef<M::Type> for Object<M> {
109    fn as_ref(&self) -> &M::Type {
110        self
111    }
112}
113
114impl<M: Manager> AsMut<M::Type> for Object<M> {
115    fn as_mut(&mut self) -> &mut M::Type {
116        self
117    }
118}
119
120/// A unique identifier for an object within a pool.
121///
122/// `ObjectId` is an opaque wrapper around a numeric identifier.
123/// IDs are guaranteed to be unique and monotonically increasing
124/// **within a single pool**. Each new object receives an identifier
125/// greater than the previously created object, but IDs are not
126/// guaranteed to be consecutive (gaps may exist).
127///
128/// This type is intended to be used as an opaque handle for
129/// identifying objects. It implements common traits such as
130/// [`Copy`], [`Clone`], [`Eq`], [`Ord`], and [`Hash`] so that
131/// it can be compared, ordered, or stored in sets and maps.
132/// It should not be used for arithmetic or treated as a raw number.
133#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
134pub struct ObjectId(usize);
135
136impl fmt::Display for ObjectId {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        write!(f, "{}", self.0)
139    }
140}