async_object_pool/
lib.rs

1use async_std::sync::{Condvar, Mutex};
2
3pub struct Pool<T> {
4    sync_tuple: Mutex<(Vec<T>, usize)>,
5    condvar: Condvar,
6    create_max: usize
7}
8
9impl<T> Pool<T> {
10    pub fn new(create_max: usize) -> Self {
11        Self {
12            sync_tuple: Mutex::new((Vec::new(), 0)),
13            condvar: Condvar::new(),
14            create_max,
15        }
16    }
17
18    pub async fn put(&self, item: T) {
19        let mut lock_guard = (&self.sync_tuple).lock().await;
20        (*lock_guard).0.push(item);
21        self.condvar.notify_one();
22    }
23
24    pub async fn take_or_create<F>(&self, creator_fn: F) -> T where
25        F: Fn() -> T {
26        let mut lock_guard = (&self.sync_tuple).lock().await;
27
28        while (*lock_guard).0.is_empty() && (*lock_guard).1 == self.create_max {
29            lock_guard = self.condvar.wait(lock_guard).await;
30        }
31
32        if (*lock_guard).1 < self.create_max {
33            (*lock_guard).0.push((creator_fn)());
34            (*lock_guard).1 += 1;
35        }
36
37        return (*lock_guard).0.remove(0);
38    }
39}
40
41
42#[cfg(test)]
43mod tests {
44    use async_std::task;
45    use crate::Pool;
46
47    #[test]
48    fn usage_example() -> std::io::Result<()> {
49        task::block_on(async {
50            // Create a new pool that will allow to create at most 100 items
51            let pool = Pool::new(100);
52
53            // Take an item from the pool or create a new item if the pool is empty
54            // but the maximum number of pooled items was not created yet.
55            // This will asynchronously block execution until an item can be returned.
56            let item = pool.take_or_create(|| String::from("hello")).await;
57
58            // Use your item
59            println!("{}", item);
60
61            // After using the item, put it back into the pool so it can be reused elsewhere
62            pool.put(item).await;
63        });
64        Ok(())
65    }
66}