1use 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
39pub 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 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}