summaryrefslogtreecommitdiffstats
path: root/third_party/rust/futures-task/src/spawn.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/futures-task/src/spawn.rs')
-rw-r--r--third_party/rust/futures-task/src/spawn.rs192
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()
+ }
+ }
+}