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> {}