charms 13.0.0

Programmable assets on Bitcoin and beyond
Documentation
use std::{
    mem::ManuallyDrop,
    sync::{Mutex, mpsc},
};

pub struct Pool<T> {
    tx: mpsc::Sender<()>,
    rx: Mutex<mpsc::Receiver<()>>,
    stack: Mutex<Vec<T>>,
}

pub struct LifeGuard<'a, T> {
    pool: &'a Pool<T>,
    value: ManuallyDrop<T>,
}

impl<'a, T> std::ops::Deref for LifeGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

impl<'a, T> Drop for LifeGuard<'a, T> {
    fn drop(&mut self) {
        self.pool
            .push(unsafe { ManuallyDrop::take(&mut self.value) });
    }
}

impl<T> Pool<T> {
    pub fn new() -> Self {
        let (tx, rx) = mpsc::channel();
        let rx = Mutex::new(rx);
        let stack = Mutex::new(vec![]);
        Self { tx, rx, stack }
    }

    pub fn pull(&self) -> LifeGuard<'_, T> {
        let _ = self.rx.lock().unwrap().recv().unwrap();
        let v = self.stack.lock().unwrap().pop().unwrap();
        LifeGuard {
            pool: &self,
            value: ManuallyDrop::new(v),
        }
    }

    pub fn push(&self, v: T) {
        self.stack.lock().unwrap().push(v);
        self.tx.send(()).unwrap();
    }
}