use std::sync::{Arc, Mutex}; pub struct Pool { create_item: Box T>, max_items: usize, state: Arc>>, } struct State { n_items_outstanding: usize, available_items: Vec, } impl Pool { pub fn new(max_items: usize, create_item: Box T>) -> Pool { Pool { create_item, max_items, state: Arc::new(Mutex::new(State { n_items_outstanding: 0, available_items: Vec::new(), })), } } pub fn get(&self) -> Option> { let mut state = self.state.lock().unwrap(); if let Some(item) = state.available_items.pop() { state.n_items_outstanding += 1; Some(PoolItem { item: Some(item), state: self.state.clone(), }) } else if state.n_items_outstanding < self.max_items { state.n_items_outstanding += 1; let item = (self.create_item)(); Some(PoolItem { item: Some(item), state: self.state.clone(), }) } else { None } } } pub struct PoolItem { item: Option, state: Arc>>, } impl std::ops::Deref for PoolItem { type Target = T; fn deref(&self) -> &Self::Target { self.item.as_ref().unwrap() } } impl std::ops::DerefMut for PoolItem { fn deref_mut(&mut self) -> &mut Self::Target { self.item.as_mut().unwrap() } } impl Drop for PoolItem { fn drop(&mut self) { let mut state = self.state.lock().unwrap(); state.available_items.push(self.item.take().unwrap()); state.n_items_outstanding -= 1; } }