1#![doc = include_str!("../README.MD")]
2#![warn(missing_docs)]
3
4use std::fmt::Debug;
5
6use std::future::Future;
7
8mod extensions;
9pub mod prelude;
10mod utils;
11
12#[cfg(any(feature = "bevy_runtime", feature = "bevy_runtime_018"))]
13pub mod bevy;
14
15#[cfg(feature = "futures_runtime")]
16pub mod futures;
17
18#[cfg(feature = "tokio_runtime")]
19pub mod tokio;
20
21pub use utils::Infallible;
22
23#[cfg(feature = "compat")]
24pub use extensions::compat;
25
26#[cfg(feature = "http")]
27pub use extensions::http;
28
29#[cfg(feature = "time")]
30pub use extensions::time;
31
32pub trait TaskHandle {
34 type Output;
36 type JoinError: Debug;
38 fn join(self) -> impl Future<Output = Result<Self::Output, Self::JoinError>>;
40 fn abort(self);
42 fn cancel(self) -> impl Future<Output = ()> + Send;
44 fn detach(self);
46}
47
48pub trait TaskReturnHandle {
50 type Error;
52 fn detach(self) -> Result<(), Self::Error>;
54}
55
56impl<TH, E> TaskReturnHandle for Result<TH, E>
57where
58 TH: TaskHandle,
59{
60 type Error = E;
61 fn detach(self) -> Result<(), Self::Error> {
62 self.map(|x| x.detach())
63 }
64}
65
66pub trait TaskInterface: Send + Sync + Clone + 'static {
68 type TaskHandle<T: 'static + Send>: TaskHandle<Output = T, JoinError = Self::JoinError>;
70
71 type SpawnError: Debug;
73
74 type JoinError: Debug;
76
77 fn spawn_task<F, T>(
79 &self,
80 future: F,
81 ) -> Result<utils::TaskHandle<Self::TaskHandle<F::Output>>, Self::SpawnError>
82 where
83 F: Future<Output = T> + Send + 'static,
84 T: Send + 'static;
85
86 fn block_on<F: Future>(&self, future: F) -> F::Output;
88}
89
90pub struct Config {
92 pub(crate) thread_count: Option<usize>,
93 pub(crate) prefix: Option<String>,
94}
95
96impl Config {
97 pub fn new() -> Self {
99 Self {
100 thread_count: None,
101 prefix: None,
102 }
103 }
104 pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
106 self.prefix = Some(prefix.into());
107 self
108 }
109 pub fn thread_count(mut self, thread_count: usize) -> Self {
111 self.thread_count = Some(thread_count);
112 self
113 }
114}
115
116impl Default for Config {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122pub trait CreationInterface: TaskInterface {
124 type NewError: Debug;
126
127 fn new(config: Config) -> Result<Self, Self::NewError>;
129}
130
131#[cfg(test)]
132#[path = "../tests/common/mod.rs"]
133mod common;
134
135#[cfg(all(test, any(feature = "futures_runtime", feature = "tokio_runtime")))]
136mod test {
137 use super::common;
138
139 use crate::{Config, CreationInterface};
140
141 fn test_full_runtime<RT: CreationInterface>() {
142 let rt = RT::new(Config::new().prefix("test")).unwrap();
143 common::test_runtime_tasks(&rt);
144 }
145 #[cfg(feature = "futures_runtime")]
146 #[test]
147 fn test_futures() {
148 test_full_runtime::<crate::futures::Runtime>();
149 }
150 #[cfg(feature = "tokio_runtime")]
151 #[test]
152 fn test_tokio() {
153 test_full_runtime::<crate::tokio::Runtime>();
154 }
155}