Skip to main content

base_pool/
retirement.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::{
5    ResourceId,
6    core::{Accounting, lock},
7};
8use std::{
9    collections::VecDeque,
10    ops::{Deref, DerefMut},
11    sync::{Arc, Mutex},
12};
13
14pub(crate) struct RetirementQueue<R> {
15    items: Mutex<VecDeque<(ResourceId, R)>>,
16    accounting: Arc<Accounting>,
17}
18impl<R> RetirementQueue<R> {
19    pub fn new(accounting: Arc<Accounting>) -> Self {
20        Self {
21            items: Mutex::new(VecDeque::new()),
22            accounting,
23        }
24    }
25    pub fn push(&self, id: ResourceId, resource: R) {
26        lock(&self.items).push_back((id, resource));
27        self.accounting.notify();
28    }
29    pub fn pop(self: &Arc<Self>) -> Option<Retirement<R>> {
30        let item = lock(&self.items).pop_front();
31        item.map(|item| Retirement {
32            item: Some(item),
33            queue: self.clone(),
34        })
35    }
36}
37
38/// A resource charged to the pool until its owner acknowledges cleanup.
39/// Await resource-specific retirement through this handle, then call `complete`.
40/// Dropping it unfinished requeues it and retains capacity; no task is spawned.
41/// Dropping all pool/lease/retirement owners performs only ordinary destruction.
42pub struct Retirement<R> {
43    item: Option<(ResourceId, R)>,
44    queue: Arc<RetirementQueue<R>>,
45}
46impl<R> Retirement<R> {
47    pub fn id(&self) -> ResourceId {
48        self.item.as_ref().unwrap().0
49    }
50    /// Acknowledge completed cleanup, destroy the retained resource, then free
51    /// capacity. This call does not perform asynchronous I/O on the resource.
52    pub fn complete(mut self) {
53        drop(self.item.take().unwrap());
54        lock(&self.queue.accounting.counts).retiring -= 1;
55        self.queue.accounting.notify();
56    }
57}
58impl<R> Deref for Retirement<R> {
59    type Target = R;
60    fn deref(&self) -> &R {
61        &self.item.as_ref().unwrap().1
62    }
63}
64impl<R> DerefMut for Retirement<R> {
65    fn deref_mut(&mut self) -> &mut R {
66        &mut self.item.as_mut().unwrap().1
67    }
68}
69impl<R> Drop for Retirement<R> {
70    fn drop(&mut self) {
71        if let Some((id, resource)) = self.item.take() {
72            self.queue.push(id, resource);
73        }
74    }
75}