futures_scopes/
scoped_spawn.rs

1use std::future::Future;
2
3use futures::future::{FutureExt, RemoteHandle};
4use futures::task::{FutureObj, SpawnError};
5
6/// A scope that can spawn non-static futures
7pub trait ScopedSpawn<'sc, T> {
8    /// Spawns a task that polls the given future.
9    ///
10    /// This method returns a [`Result`] that contains a [`SpawnError`] if spawning fails.
11    fn spawn_obj_scoped(&self, future: FutureObj<'sc, T>) -> Result<(), SpawnError>;
12
13    /// Determines whether the scope is able to spawn new tasks.
14    ///
15    /// This method will return `Ok` when the scope is *likely*
16    /// (but not guaranteed) to accept a subsequent spawn attempt.
17    /// Likewise, an `Err` return means that `spawn` is likely, but
18    /// not guaranteed, to yield an error.
19    #[inline]
20    fn status_scoped(&self) -> Result<(), SpawnError> {
21        Ok(())
22    }
23}
24
25/// Extension trait for `ScopedSpawn`.
26pub trait ScopedSpawnExt<'a, T>: ScopedSpawn<'a, T> {
27    /// Spawns a task that polls the given future.
28    ///
29    /// This method returns a [`Result`] that contains a [`SpawnError`] if spawning fails.
30    fn spawn_scoped<Fut>(&self, future: Fut) -> Result<(), SpawnError>
31    where
32        Fut: Future<Output = T> + Send + 'a,
33    {
34        self.spawn_obj_scoped(FutureObj::new(Box::new(future)))
35    }
36
37    /// Spawns a task that polls the given future and returns a handle to its output.
38    ///
39    /// This method returns a [`Result`] that contains a [`SpawnError`] if spawning fails.
40    fn spawn_scoped_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError>
41    where
42        Fut: Future + Send + 'a,
43        Fut::Output: Send + 'a,
44        Self: ScopedSpawnExt<'a, ()>,
45    {
46        let (remote, handle) = future.remote_handle();
47        let _: () = self.spawn_scoped(remote)?;
48        Ok(handle)
49    }
50}
51
52impl<'sc, T, Sp: ?Sized> ScopedSpawnExt<'sc, T> for Sp where Sp: ScopedSpawn<'sc, T> {}