1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
#[ allow(unused_imports) ]
//
use
{
futures_util :: { future::{ FutureExt, abortable }, task::SpawnExt } ,
futures_task :: { SpawnError, FutureObj } ,
crate :: { JoinHandle } ,
std :: { pin::Pin, future::Future, sync::{ Arc, atomic::AtomicBool }, rc::Rc } ,
blanket :: { blanket } ,
};
/// Lets you spawn and get a [JoinHandle] to await the output of a future.
///
/// This trait works much like the [`Spawn`](futures_task::Spawn) trait from the futures library.
/// It takes a [`FutureObj`] so we can hopefully make it `no_std` compatible when needed. This
/// also allows it to be object safe. For convenience, there is [`SpawnHandleExt`] which allows you
/// to spawn a generic future directly without having to manually make the [`FutureObj`].
///
/// [`SpawnHandleExt`] is automatically implemented but must be in scope, so this works:
///
/// ```rust
/// use async_executors::{ SpawnHandle, SpawnHandleExt };
///
/// async fn need_exec( exec: impl SpawnHandle<()> )
/// {
/// let join_handle = exec.spawn_handle( async {} ).expect( "spawn" );
///
/// join_handle.await;
/// }
/// ```
///
/// and so does this:
///
/// ```rust
/// use async_executors::{ SpawnHandle, SpawnHandleExt };
///
/// async fn need_exec( exec: Box< dyn SpawnHandle<()> > )
/// {
/// let join_handle = exec.spawn_handle( async {} ).expect( "spawn" );
///
/// join_handle.await;
/// }
/// ```
///
/// One inconvenience of it having to be object safe is that the trait needs to be generic over the
/// output parameter. This can be annoying if you need an executor that can spawn futures with different
/// output parameters. Normally you should always be able to know which ones you need. If not
/// you will have to make the type that stores the executor generic over the output type as well.
///
/// So to enable several output types you can use the
/// [following workaround](https://github.com/najamelan/async_executors/tree/master/examples/spawn_handle_multi.rs).
/// You can also use the [trait-set](https://crates.io/crates/trait-set) crate to make that [more streamlined](https://github.com/najamelan/async_executors/tree/master/examples/trait_set.rs).
//
#[ blanket(derive( Ref, Mut, Box, Arc, Rc )) ]
//
pub trait SpawnHandle<Out: 'static + Send>
{
/// Spawn a future and return a [`JoinHandle`] that can be awaited for the output of the future.
//
fn spawn_handle_obj( &self, future: FutureObj<'static, Out> ) -> Result<JoinHandle<Out>, SpawnError>;
}
/// Convenience trait for passing in a generic future to [`SpawnHandle`]. Much akin to `Spawn` and `SpawnExt` in the
/// futures library.
//
pub trait SpawnHandleExt<Out: 'static + Send> : SpawnHandle<Out>
{
/// Spawn a future and return a [JoinHandle] that can be awaited for the output of the future.
//
fn spawn_handle( &self, future: impl Future<Output = Out> + Send + 'static ) -> Result<JoinHandle<Out>, SpawnError>;
}
impl<T, Out> SpawnHandleExt<Out> for T
where T : SpawnHandle<Out> + ?Sized ,
Out: 'static + Send ,
{
fn spawn_handle( &self, future: impl Future<Output = Out> + Send + 'static ) -> Result<JoinHandle<Out>, SpawnError>
{
self.spawn_handle_obj( FutureObj::new(future.boxed()) )
}
}