bevy_tasks/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc(
4    html_logo_url = "https://bevyengine.org/assets/icon.png",
5    html_favicon_url = "https://bevyengine.org/assets/icon.png"
6)]
7#![no_std]
8
9#[cfg(feature = "std")]
10extern crate std;
11
12extern crate alloc;
13
14mod conditional_send {
15    cfg_if::cfg_if! {
16        if #[cfg(target_arch = "wasm32")] {
17            /// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
18            /// futures aren't Send.
19            pub trait ConditionalSend {}
20            impl<T> ConditionalSend for T {}
21        } else {
22            /// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm),
23            /// futures aren't Send.
24            pub trait ConditionalSend: Send {}
25            impl<T: Send> ConditionalSend for T {}
26        }
27    }
28}
29
30pub use conditional_send::*;
31
32/// Use [`ConditionalSendFuture`] for a future with an optional Send trait bound, as on certain platforms (eg. Wasm),
33/// futures aren't Send.
34pub trait ConditionalSendFuture: Future + ConditionalSend {}
35impl<T: Future + ConditionalSend> ConditionalSendFuture for T {}
36
37use alloc::boxed::Box;
38
39/// An owned and dynamically typed Future used when you can't statically type your result or need to add some indirection.
40pub type BoxedFuture<'a, T> = core::pin::Pin<Box<dyn ConditionalSendFuture<Output = T> + 'a>>;
41
42pub mod futures;
43
44#[cfg(not(feature = "async_executor"))]
45mod edge_executor;
46
47mod executor;
48
49mod slice;
50pub use slice::{ParallelSlice, ParallelSliceMut};
51
52#[cfg_attr(all(target_arch = "wasm32", feature = "web"), path = "wasm_task.rs")]
53mod task;
54
55pub use task::Task;
56
57cfg_if::cfg_if! {
58    if #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] {
59        mod task_pool;
60        mod thread_executor;
61
62        pub use task_pool::{Scope, TaskPool, TaskPoolBuilder};
63        pub use thread_executor::{ThreadExecutor, ThreadExecutorTicker};
64    } else if #[cfg(any(target_arch = "wasm32", not(feature = "multi_threaded")))] {
65        mod single_threaded_task_pool;
66
67        pub use single_threaded_task_pool::{Scope, TaskPool, TaskPoolBuilder, ThreadExecutor};
68    }
69}
70
71mod usages;
72pub use futures_lite::future::poll_once;
73pub use usages::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool};
74
75#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
76pub use usages::tick_global_task_pools_on_main_thread;
77
78#[cfg(feature = "std")]
79cfg_if::cfg_if! {
80    if #[cfg(feature = "async-io")] {
81        pub use async_io::block_on;
82    } else {
83        pub use futures_lite::future::block_on;
84    }
85}
86
87mod iter;
88pub use iter::ParallelIterator;
89
90pub use futures_lite;
91
92/// The tasks prelude.
93///
94/// This includes the most common types in this crate, re-exported for your convenience.
95pub mod prelude {
96    #[doc(hidden)]
97    pub use crate::{
98        iter::ParallelIterator,
99        slice::{ParallelSlice, ParallelSliceMut},
100        usages::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool},
101    };
102
103    #[cfg(feature = "std")]
104    #[doc(hidden)]
105    pub use crate::block_on;
106}
107
108cfg_if::cfg_if! {
109    if #[cfg(feature = "std")] {
110        use core::num::NonZero;
111
112        /// Gets the logical CPU core count available to the current process.
113        ///
114        /// This is identical to [`std::thread::available_parallelism`], except
115        /// it will return a default value of 1 if it internally errors out.
116        ///
117        /// This will always return at least 1.
118        pub fn available_parallelism() -> usize {
119            std::thread::available_parallelism()
120                .map(NonZero::<usize>::get)
121                .unwrap_or(1)
122        }
123    } else {
124        /// Gets the logical CPU core count available to the current process.
125        ///
126        /// This will always return at least 1.
127        pub fn available_parallelism() -> usize {
128            // Without access to std, assume a single thread is available
129            1
130        }
131    }
132}