diff options
Diffstat (limited to 'third_party/rust/futures-task/src/spawn.rs')
-rw-r--r-- | third_party/rust/futures-task/src/spawn.rs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/third_party/rust/futures-task/src/spawn.rs b/third_party/rust/futures-task/src/spawn.rs new file mode 100644 index 0000000000..f4e63397bd --- /dev/null +++ b/third_party/rust/futures-task/src/spawn.rs @@ -0,0 +1,192 @@ +use crate::{FutureObj, LocalFutureObj}; +use core::fmt; + +/// The `Spawn` trait allows for pushing futures onto an executor that will +/// run them to completion. +pub trait Spawn { + /// Spawns a future that will be run to completion. + /// + /// # Errors + /// + /// The executor may be unable to spawn tasks. Spawn errors should + /// represent relatively rare scenarios, such as the executor + /// having been shut down so that it is no longer able to accept + /// tasks. + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError>; + + /// Determines whether the executor is able to spawn new tasks. + /// + /// This method will return `Ok` when the executor is *likely* + /// (but not guaranteed) to accept a subsequent spawn attempt. + /// Likewise, an `Err` return means that `spawn` is likely, but + /// not guaranteed, to yield an error. + #[inline] + fn status(&self) -> Result<(), SpawnError> { + Ok(()) + } +} + +/// The `LocalSpawn` is similar to [`Spawn`], but allows spawning futures +/// that don't implement `Send`. +pub trait LocalSpawn { + /// Spawns a future that will be run to completion. + /// + /// # Errors + /// + /// The executor may be unable to spawn tasks. Spawn errors should + /// represent relatively rare scenarios, such as the executor + /// having been shut down so that it is no longer able to accept + /// tasks. + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError>; + + /// Determines whether the executor is able to spawn new tasks. + /// + /// This method will return `Ok` when the executor is *likely* + /// (but not guaranteed) to accept a subsequent spawn attempt. + /// Likewise, an `Err` return means that `spawn` is likely, but + /// not guaranteed, to yield an error. + #[inline] + fn status_local(&self) -> Result<(), SpawnError> { + Ok(()) + } +} + +/// An error that occurred during spawning. +pub struct SpawnError { + _priv: (), +} + +impl fmt::Debug for SpawnError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SpawnError").field(&"shutdown").finish() + } +} + +impl fmt::Display for SpawnError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Executor is shutdown") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SpawnError {} + +impl SpawnError { + /// Spawning failed because the executor has been shut down. + pub fn shutdown() -> Self { + Self { _priv: () } + } + + /// Check whether spawning failed to the executor being shut down. + pub fn is_shutdown(&self) -> bool { + true + } +} + +impl<Sp: ?Sized + Spawn> Spawn for &Sp { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_obj(self, future) + } + + fn status(&self) -> Result<(), SpawnError> { + Sp::status(self) + } +} + +impl<Sp: ?Sized + Spawn> Spawn for &mut Sp { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_obj(self, future) + } + + fn status(&self) -> Result<(), SpawnError> { + Sp::status(self) + } +} + +impl<Sp: ?Sized + LocalSpawn> LocalSpawn for &Sp { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_local_obj(self, future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + Sp::status_local(self) + } +} + +impl<Sp: ?Sized + LocalSpawn> LocalSpawn for &mut Sp { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_local_obj(self, future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + Sp::status_local(self) + } +} + +#[cfg(feature = "alloc")] +mod if_alloc { + use super::*; + use alloc::{boxed::Box, rc::Rc}; + + impl<Sp: ?Sized + Spawn> Spawn for Box<Sp> { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + impl<Sp: ?Sized + LocalSpawn> LocalSpawn for Box<Sp> { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } + + impl<Sp: ?Sized + Spawn> Spawn for Rc<Sp> { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + impl<Sp: ?Sized + LocalSpawn> LocalSpawn for Rc<Sp> { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } + + #[cfg(not(futures_no_atomic_cas))] + impl<Sp: ?Sized + Spawn> Spawn for alloc::sync::Arc<Sp> { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + #[cfg(not(futures_no_atomic_cas))] + impl<Sp: ?Sized + LocalSpawn> LocalSpawn for alloc::sync::Arc<Sp> { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } +} |