1use std::{future::Future, num::NonZeroU32, sync::Mutex};
2use tokio::sync::Semaphore;
3
4pub async fn await_and_every_sec<RetT>(
5 mut fut: impl Future<Output = RetT> + Unpin,
6 mut periodic: impl FnMut(),
7) -> RetT {
8 loop {
9 tokio::select! {
10 ret = &mut fut => {
11 return ret;
12 }
13 _ = tokio::time::sleep(std::time::Duration::from_secs(1)) => {
14 periodic();
15 }
16 }
17 }
18}
19
20pub struct Pool<T> {
21 mutex: Mutex<Vec<T>>,
22 semaphore: Semaphore,
23}
24
25impl<T> Pool<T> {
26 pub fn new(slots: NonZeroU32) -> Self {
27 Self {
28 mutex: Default::default(),
29 semaphore: Semaphore::new(usize::try_from(u32::from(slots)).unwrap()),
30 }
31 }
32
33 pub async fn call_with_item<U, E, F, Fut>(&self, f: F) -> Result<U, E>
40 where
41 F: FnOnce(Option<T>) -> Fut,
42 Fut: Future<Output = Result<(T, U), E>>,
43 {
44 let _permit = self.semaphore.acquire().await.unwrap();
45 let item = self.mutex.lock().unwrap().pop();
46 f(item).await.map(|(item, ret)| {
47 self.mutex.lock().unwrap().push(item);
48 ret
49 })
50 }
51}