diff options
Diffstat (limited to 'third_party/rust/futures-util/src/task')
-rw-r--r-- | third_party/rust/futures-util/src/task/mod.rs | 37 | ||||
-rw-r--r-- | third_party/rust/futures-util/src/task/spawn.rs | 169 |
2 files changed, 206 insertions, 0 deletions
diff --git a/third_party/rust/futures-util/src/task/mod.rs b/third_party/rust/futures-util/src/task/mod.rs new file mode 100644 index 0000000000..0a31eeac14 --- /dev/null +++ b/third_party/rust/futures-util/src/task/mod.rs @@ -0,0 +1,37 @@ +//! Tools for working with tasks. +//! +//! This module contains: +//! +//! - [`Spawn`], a trait for spawning new tasks. +//! - [`Context`], a context of an asynchronous task, +//! including a handle for waking up the task. +//! - [`Waker`], a handle for waking up a task. +//! +//! The remaining types and traits in the module are used for implementing +//! executors or dealing with synchronization issues around task wakeup. + +#[doc(no_inline)] +pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; + +pub use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError, UnsafeFutureObj}; + +pub use futures_task::noop_waker; +pub use futures_task::noop_waker_ref; + +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +pub use futures_task::ArcWake; + +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +pub use futures_task::waker; + +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +pub use futures_task::{waker_ref, WakerRef}; + +#[cfg(not(futures_no_atomic_cas))] +pub use futures_core::task::__internal::AtomicWaker; + +mod spawn; +pub use self::spawn::{LocalSpawnExt, SpawnExt}; diff --git a/third_party/rust/futures-util/src/task/spawn.rs b/third_party/rust/futures-util/src/task/spawn.rs new file mode 100644 index 0000000000..d9e9985309 --- /dev/null +++ b/third_party/rust/futures-util/src/task/spawn.rs @@ -0,0 +1,169 @@ +use futures_task::{LocalSpawn, Spawn}; + +#[cfg(feature = "compat")] +use crate::compat::Compat; + +#[cfg(feature = "channel")] +#[cfg(feature = "std")] +use crate::future::{FutureExt, RemoteHandle}; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use futures_core::future::Future; +#[cfg(feature = "alloc")] +use futures_task::{FutureObj, LocalFutureObj, SpawnError}; + +impl<Sp: ?Sized> SpawnExt for Sp where Sp: Spawn {} +impl<Sp: ?Sized> LocalSpawnExt for Sp where Sp: LocalSpawn {} + +/// Extension trait for `Spawn`. +pub trait SpawnExt: Spawn { + /// Spawns a task that polls the given future with output `()` to + /// completion. + /// + /// This method returns a [`Result`] that contains a [`SpawnError`] if + /// spawning fails. + /// + /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if + /// you want to spawn a future with output other than `()` or if you want + /// to be able to await its completion. + /// + /// Note this method will eventually be replaced with the upcoming + /// `Spawn::spawn` method which will take a `dyn Future` as input. + /// Technical limitations prevent `Spawn::spawn` from being implemented + /// today. Feel free to use this method in the meantime. + /// + /// ``` + /// # { + /// use futures::executor::ThreadPool; + /// use futures::task::SpawnExt; + /// + /// let executor = ThreadPool::new().unwrap(); + /// + /// let future = async { /* ... */ }; + /// executor.spawn(future).unwrap(); + /// # } + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + #[cfg(feature = "alloc")] + fn spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError> + where + Fut: Future<Output = ()> + Send + 'static, + { + self.spawn_obj(FutureObj::new(Box::new(future))) + } + + /// Spawns a task that polls the given future to completion and returns a + /// future that resolves to the spawned future's output. + /// + /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if + /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that + /// resolves to the output of the spawned future. + /// + /// ``` + /// # { + /// use futures::executor::{block_on, ThreadPool}; + /// use futures::future; + /// use futures::task::SpawnExt; + /// + /// let executor = ThreadPool::new().unwrap(); + /// + /// let future = future::ready(1); + /// let join_handle_fut = executor.spawn_with_handle(future).unwrap(); + /// assert_eq!(block_on(join_handle_fut), 1); + /// # } + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn spawn_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError> + where + Fut: Future + Send + 'static, + Fut::Output: Send, + { + let (future, handle) = future.remote_handle(); + self.spawn(future)?; + Ok(handle) + } + + /// Wraps a [`Spawn`] and makes it usable as a futures 0.1 `Executor`. + /// Requires the `compat` feature to enable. + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> Compat<Self> + where + Self: Sized, + { + Compat::new(self) + } +} + +/// Extension trait for `LocalSpawn`. +pub trait LocalSpawnExt: LocalSpawn { + /// Spawns a task that polls the given future with output `()` to + /// completion. + /// + /// This method returns a [`Result`] that contains a [`SpawnError`] if + /// spawning fails. + /// + /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if + /// you want to spawn a future with output other than `()` or if you want + /// to be able to await its completion. + /// + /// Note this method will eventually be replaced with the upcoming + /// `Spawn::spawn` method which will take a `dyn Future` as input. + /// Technical limitations prevent `Spawn::spawn` from being implemented + /// today. Feel free to use this method in the meantime. + /// + /// ``` + /// use futures::executor::LocalPool; + /// use futures::task::LocalSpawnExt; + /// + /// let executor = LocalPool::new(); + /// let spawner = executor.spawner(); + /// + /// let future = async { /* ... */ }; + /// spawner.spawn_local(future).unwrap(); + /// ``` + #[cfg(feature = "alloc")] + fn spawn_local<Fut>(&self, future: Fut) -> Result<(), SpawnError> + where + Fut: Future<Output = ()> + 'static, + { + self.spawn_local_obj(LocalFutureObj::new(Box::new(future))) + } + + /// Spawns a task that polls the given future to completion and returns a + /// future that resolves to the spawned future's output. + /// + /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if + /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that + /// resolves to the output of the spawned future. + /// + /// ``` + /// use futures::executor::LocalPool; + /// use futures::task::LocalSpawnExt; + /// + /// let mut executor = LocalPool::new(); + /// let spawner = executor.spawner(); + /// + /// let future = async { 1 }; + /// let join_handle_fut = spawner.spawn_local_with_handle(future).unwrap(); + /// assert_eq!(executor.run_until(join_handle_fut), 1); + /// ``` + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn spawn_local_with_handle<Fut>( + &self, + future: Fut, + ) -> Result<RemoteHandle<Fut::Output>, SpawnError> + where + Fut: Future + 'static, + { + let (future, handle) = future.remote_handle(); + self.spawn_local(future)?; + Ok(handle) + } +} |