Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_tasks/src/lib.rs
6604 views
1
#![doc = include_str!("../README.md")]
2
#![cfg_attr(docsrs, feature(doc_auto_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
9
/// Configuration information for this crate.
10
pub 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
/// Indicates `async_executor` is used as the future execution backend.
18
async_executor
19
}
20
21
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] => {
22
/// Indicates multithreading support.
23
multi_threaded
24
}
25
26
#[cfg(target_arch = "wasm32")] => {
27
/// Indicates the current target requires additional `Send` bounds.
28
conditional_send
29
}
30
31
#[cfg(feature = "async-io")] => {
32
/// Indicates `async-io` will be used for the implementation of `block_on`.
33
async_io
34
}
35
36
#[cfg(feature = "futures-lite")] => {
37
/// Indicates `futures-lite` will be used for the implementation of `block_on`.
38
futures_lite
39
}
40
}
41
}
42
43
cfg::std! {
44
extern crate std;
45
}
46
47
extern crate alloc;
48
49
cfg::conditional_send! {
50
if {
51
/// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
52
/// futures aren't Send.
53
pub trait ConditionalSend {}
54
impl<T> ConditionalSend for T {}
55
} else {
56
/// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
57
/// futures aren't Send.
58
pub trait ConditionalSend: Send {}
59
impl<T: Send> ConditionalSend for T {}
60
}
61
}
62
63
/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
64
/// futures aren't Send.
65
pub trait ConditionalSendFuture: Future + ConditionalSend {}
66
67
impl<T: Future + ConditionalSend> ConditionalSendFuture for T {}
68
69
use alloc::boxed::Box;
70
71
/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
72
pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
73
74
// Modules
75
mod executor;
76
pub mod futures;
77
mod iter;
78
mod slice;
79
mod task;
80
mod usages;
81
82
cfg::async_executor! {
83
if {} else {
84
mod edge_executor;
85
}
86
}
87
88
// Exports
89
pub use iter::ParallelIterator;
90
pub use slice::{ParallelSlice, ParallelSliceMut};
91
pub use task::Task;
92
pub use usages::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool};
93
94
pub use futures_lite;
95
pub use futures_lite::future::poll_once;
96
97
cfg::web! {
98
if {} else {
99
pub use usages::tick_global_task_pools_on_main_thread;
100
}
101
}
102
103
cfg::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
117
cfg::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
/// Blocks on the supplied `future`.
126
/// This implementation will busy-wait until it is completed.
127
/// Consider enabling the `async-io` or `futures-lite` features.
128
pub fn block_on<T>(future: impl Future<Output = T>) -> T {
129
use core::task::{Poll, Context};
130
131
// Pin the future on the stack.
132
let mut future = core::pin::pin!(future);
133
134
// We don't care about the waker as we're just going to poll as fast as possible.
135
let cx = &mut Context::from_waker(core::task::Waker::noop());
136
137
// Keep polling until the future is ready.
138
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
148
/// The tasks prelude.
149
///
150
/// This includes the most common types in this crate, re-exported for your convenience.
151
pub 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
161
/// Gets the logical CPU core count available to the current process.
162
///
163
/// This is identical to `std::thread::available_parallelism`, except
164
/// it will return a default value of 1 if it internally errors out.
165
///
166
/// This will always return at least 1.
167
pub 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
}
179
180