bevy_tasks/
usages.rs

1use super::TaskPool;
2use core::ops::Deref;
3use std::sync::OnceLock;
4
5macro_rules! taskpool {
6    ($(#[$attr:meta])* ($static:ident, $type:ident)) => {
7        static $static: OnceLock<$type> = OnceLock::new();
8
9        $(#[$attr])*
10        #[derive(Debug)]
11        pub struct $type(TaskPool);
12
13        impl $type {
14            #[doc = concat!(" Gets the global [`", stringify!($type), "`] instance, or initializes it with `f`.")]
15            pub fn get_or_init(f: impl FnOnce() -> TaskPool) -> &'static Self {
16                $static.get_or_init(|| Self(f()))
17            }
18
19            #[doc = concat!(" Attempts to get the global [`", stringify!($type), "`] instance, \
20                or returns `None` if it is not initialized.")]
21            pub fn try_get() -> Option<&'static Self> {
22                $static.get()
23            }
24
25            #[doc = concat!(" Gets the global [`", stringify!($type), "`] instance.")]
26            #[doc = ""]
27            #[doc = " # Panics"]
28            #[doc = " Panics if the global instance has not been initialized yet."]
29            pub fn get() -> &'static Self {
30                $static.get().expect(
31                    concat!(
32                        "The ",
33                        stringify!($type),
34                        " has not been initialized yet. Please call ",
35                        stringify!($type),
36                        "::get_or_init beforehand."
37                    )
38                )
39            }
40        }
41
42        impl Deref for $type {
43            type Target = TaskPool;
44
45            fn deref(&self) -> &Self::Target {
46                &self.0
47            }
48        }
49    };
50}
51
52taskpool! {
53    /// A newtype for a task pool for CPU-intensive work that must be completed to
54    /// deliver the next frame
55    ///
56    /// See [`TaskPool`] documentation for details on Bevy tasks.
57    /// [`AsyncComputeTaskPool`] should be preferred if the work does not have to be
58    /// completed before the next frame.
59    (COMPUTE_TASK_POOL, ComputeTaskPool)
60}
61
62taskpool! {
63    /// A newtype for a task pool for CPU-intensive work that may span across multiple frames
64    ///
65    /// See [`TaskPool`] documentation for details on Bevy tasks.
66    /// Use [`ComputeTaskPool`] if the work must be complete before advancing to the next frame.
67    (ASYNC_COMPUTE_TASK_POOL, AsyncComputeTaskPool)
68}
69
70taskpool! {
71    /// A newtype for a task pool for IO-intensive work (i.e. tasks that spend very little time in a
72    /// "woken" state)
73    ///
74    /// See [`TaskPool`] documentation for details on Bevy tasks.
75    (IO_TASK_POOL, IoTaskPool)
76}
77
78/// A function used by `bevy_core` to tick the global tasks pools on the main thread.
79/// This will run a maximum of 100 local tasks per executor per call to this function.
80///
81/// # Warning
82///
83/// This function *must* be called on the main thread, or the task pools will not be updated appropriately.
84#[cfg(not(target_arch = "wasm32"))]
85pub fn tick_global_task_pools_on_main_thread() {
86    COMPUTE_TASK_POOL
87        .get()
88        .unwrap()
89        .with_local_executor(|compute_local_executor| {
90            ASYNC_COMPUTE_TASK_POOL
91                .get()
92                .unwrap()
93                .with_local_executor(|async_local_executor| {
94                    IO_TASK_POOL
95                        .get()
96                        .unwrap()
97                        .with_local_executor(|io_local_executor| {
98                            for _ in 0..100 {
99                                compute_local_executor.try_tick();
100                                async_local_executor.try_tick();
101                                io_local_executor.try_tick();
102                            }
103                        });
104                });
105        });
106}