futures_bounded/
futures_set.rs

1use std::future::Future;
2use std::task::{ready, Context, Poll};
3use std::time::Duration;
4
5use futures_util::future::BoxFuture;
6
7use crate::{FuturesMap, PushError, Timeout};
8
9/// Represents a list of [Future]s.
10///
11/// Each future must finish within the specified time and the list never outgrows its capacity.
12pub struct FuturesSet<O> {
13    id: u32,
14    inner: FuturesMap<u32, O>,
15}
16
17impl<O> FuturesSet<O> {
18    pub fn new(timeout: Duration, capacity: usize) -> Self {
19        Self {
20            id: 0,
21            inner: FuturesMap::new(timeout, capacity),
22        }
23    }
24}
25
26impl<O> FuturesSet<O>
27where
28    O: 'static,
29{
30    /// Push a future into the list.
31    ///
32    /// This method adds the given future to the list.
33    /// If the length of the list is equal to the capacity, this method returns a error that contains the passed future.
34    /// In that case, the future is not added to the set.
35    pub fn try_push<F>(&mut self, future: F) -> Result<(), BoxFuture<O>>
36    where
37        F: Future<Output = O> + Send + 'static,
38    {
39        self.id = self.id.wrapping_add(1);
40
41        match self.inner.try_push(self.id, future) {
42            Ok(()) => Ok(()),
43            Err(PushError::BeyondCapacity(w)) => Err(w),
44            Err(PushError::Replaced(_)) => unreachable!("we never reuse IDs"),
45        }
46    }
47
48    pub fn len(&self) -> usize {
49        self.inner.len()
50    }
51
52    pub fn is_empty(&self) -> bool {
53        self.inner.is_empty()
54    }
55
56    pub fn poll_ready_unpin(&mut self, cx: &mut Context<'_>) -> Poll<()> {
57        self.inner.poll_ready_unpin(cx)
58    }
59
60    pub fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<O, Timeout>> {
61        let (_, res) = ready!(self.inner.poll_unpin(cx));
62
63        Poll::Ready(res)
64    }
65}