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        self.accounting.retirement_changed.notify(usize::MAX);
29    }
30    pub fn pop(self: &Arc<Self>) -> Option<Retirement<R>> {
31        let item = lock(&self.items).pop_front();
32        item.map(|item| Retirement {
33            item: Some(item),
34            queue: self.clone(),
35        })
36    }
37}
38
39/// A resource charged to the pool until its owner acknowledges cleanup.
40/// Await resource-specific retirement through this handle, then call `complete`.
41/// Dropping it unfinished requeues it and retains capacity; no task is spawned.
42/// Dropping all pool/lease/retirement owners performs only ordinary destruction.
43pub struct Retirement<R> {
44    item: Option<(ResourceId, R)>,
45    queue: Arc<RetirementQueue<R>>,
46}
47impl<R> Retirement<R> {
48    pub fn id(&self) -> ResourceId {
49        self.item.as_ref().unwrap().0
50    }
51    /// Acknowledge completed cleanup, destroy the retained resource, then free
52    /// capacity. This call does not perform asynchronous I/O on the resource.
53    pub fn complete(mut self) {
54        drop(self.item.take().unwrap());
55        lock(&self.queue.accounting.counts).retiring -= 1;
56        self.queue.accounting.notify();
57        self.queue.accounting.retirement_changed.notify(usize::MAX);
58    }
59}
60impl<R> Deref for Retirement<R> {
61    type Target = R;
62    fn deref(&self) -> &R {
63        &self.item.as_ref().unwrap().1
64    }
65}
66impl<R> DerefMut for Retirement<R> {
67    fn deref_mut(&mut self) -> &mut R {
68        &mut self.item.as_mut().unwrap().1
69    }
70}
71impl<R> Drop for Retirement<R> {
72    fn drop(&mut self) {
73        if let Some((id, resource)) = self.item.take() {
74            self.queue.push(id, resource);
75        }
76    }
77}