async_object_pool/
lib.rs

1use async_lock::Mutex;
2use event_listener::Event;
3
4pub struct Pool<T> {
5    state: Mutex<(Vec<T>, usize)>,
6    ev: Event,
7    create_max: usize,
8}
9
10impl<T> Pool<T> {
11    pub fn new(create_max: usize) -> Self {
12        Self { state: Mutex::new((Vec::new(), 0)), ev: Event::new(), create_max }
13    }
14
15    pub async fn put(&self, item: T) {
16        {
17            let mut g = self.state.lock().await;
18            g.0.push(item);
19        }
20        self.ev.notify(1);
21    }
22
23    pub async fn take_or_create<F>(&self, create: F) -> T
24    where
25        F: Fn() -> T,
26    {
27        loop {
28            {
29                let mut g = self.state.lock().await;
30
31                if !g.0.is_empty() {
32                    return g.0.remove(0);
33                }
34
35                if g.1 < self.create_max {
36                    g.0.push(create());
37                    g.1 += 1;
38                    return g.0.remove(0);
39                }
40
41                let listener = self.ev.listen();
42                drop(g);
43                listener.await;  // wake when someone `put`s
44            }
45        }
46    }
47}