1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc(
4 html_logo_url = "https://bevy.org/assets/icon.png",
5 html_favicon_url = "https://bevy.org/assets/icon.png"
6)]
7#![no_std]
8
9pub mod cfg {
11 pub(crate) use bevy_platform::cfg::*;
12
13 pub use bevy_platform::cfg::{alloc, std, web};
14
15 define_alias! {
16 #[cfg(feature = "async_executor")] => {
17 async_executor
19 }
20
21 #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] => {
22 multi_threaded
24 }
25
26 #[cfg(target_arch = "wasm32")] => {
27 conditional_send
29 }
30
31 #[cfg(feature = "async-io")] => {
32 async_io
34 }
35
36 #[cfg(feature = "futures-lite")] => {
37 futures_lite
39 }
40 }
41}
42
43cfg::std! {
44 extern crate std;
45}
46
47extern crate alloc;
48
49cfg::conditional_send! {
50 if {
51 pub trait ConditionalSend {}
54 impl<T> ConditionalSend for T {}
55 } else {
56 pub trait ConditionalSend: Send {}
59 impl<T: Send> ConditionalSend for T {}
60 }
61}
62
63pub trait ConditionalSendFuture: Future + ConditionalSend {}
66
67impl<T: Future + ConditionalSend> ConditionalSendFuture for T {}
68
69use alloc::boxed::Box;
70
71pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
73
74mod executor;
76pub mod futures;
77mod iter;
78mod slice;
79mod task;
80mod usages;
81
82cfg::async_executor! {
83 if {} else {
84 mod edge_executor;
85 }
86}
87
88pub use iter::ParallelIterator;
90pub use slice::{ParallelSlice, ParallelSliceMut};
91pub use task::Task;
92pub use usages::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool};
93
94pub use futures_lite;
95pub use futures_lite::future::poll_once;
96
97cfg::web! {
98 if {} else {
99 pub use usages::tick_global_task_pools_on_main_thread;
100 }
101}
102
103cfg::multi_threaded! {
104 if {
105 mod task_pool;
106 mod thread_executor;
107
108 pub use task_pool::{Scope, TaskPool, TaskPoolBuilder};
109 pub use thread_executor::{ThreadExecutor, ThreadExecutorTicker};
110 } else {
111 mod single_threaded_task_pool;
112
113 pub use single_threaded_task_pool::{Scope, TaskPool, TaskPoolBuilder, ThreadExecutor};
114 }
115}
116
117cfg::switch! {
118 cfg::async_io => {
119 pub use async_io::block_on;
120 }
121 cfg::futures_lite => {
122 pub use futures_lite::future::block_on;
123 }
124 _ => {
125 pub fn block_on<T>(future: impl Future<Output = T>) -> T {
129 use core::task::{Poll, Context};
130
131 let mut future = core::pin::pin!(future);
133
134 let cx = &mut Context::from_waker(core::task::Waker::noop());
136
137 loop {
139 match future.as_mut().poll(cx) {
140 Poll::Ready(output) => return output,
141 Poll::Pending => core::hint::spin_loop(),
142 }
143 }
144 }
145 }
146}
147
148pub mod prelude {
152 #[doc(hidden)]
153 pub use crate::{
154 block_on,
155 iter::ParallelIterator,
156 slice::{ParallelSlice, ParallelSliceMut},
157 usages::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool},
158 };
159}
160
161pub fn available_parallelism() -> usize {
168 cfg::switch! {{
169 cfg::std => {
170 std::thread::available_parallelism()
171 .map(core::num::NonZero::<usize>::get)
172 .unwrap_or(1)
173 }
174 _ => {
175 1
176 }
177 }}
178}