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}