bevy_impulse/async_execution/
mod.rs

1/*
2 * Copyright (C) 2024 Open Source Robotics Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16*/
17
18use bevy_ecs::prelude::World;
19
20use std::future::Future;
21
22#[cfg(feature = "single_threaded_async")]
23mod single_threaded_execution;
24#[cfg(feature = "single_threaded_async")]
25pub(crate) use single_threaded_execution::SingleThreadedExecution;
26#[cfg(feature = "single_threaded_async")]
27use single_threaded_execution::SingleThreadedExecutionSender;
28
29pub(crate) use bevy_tasks::Task as TaskHandle;
30
31#[cfg(not(feature = "single_threaded_async"))]
32pub(crate) type CancelSender = AsyncComputeTaskPoolSender;
33
34#[cfg(feature = "single_threaded_async")]
35pub(crate) type CancelSender = SingleThreadedExecutionSender;
36
37pub(crate) fn spawn_task<T>(
38    future: impl Future<Output = T> + Sendish + 'static,
39    _world: &mut World,
40) -> TaskHandle<T>
41where
42    T: Send + 'static,
43{
44    #[cfg(not(feature = "single_threaded_async"))]
45    {
46        use bevy_tasks::AsyncComputeTaskPool;
47        AsyncComputeTaskPool::get().spawn(future)
48    }
49
50    #[cfg(feature = "single_threaded_async")]
51    {
52        SingleThreadedExecution::get(_world).spawn(future)
53    }
54}
55
56pub(crate) fn task_cancel_sender(_world: &mut World) -> CancelSender {
57    #[cfg(not(feature = "single_threaded_async"))]
58    {
59        AsyncComputeTaskPoolSender
60    }
61
62    #[cfg(feature = "single_threaded_async")]
63    {
64        SingleThreadedExecution::get(_world).cancel_sender()
65    }
66}
67
68#[cfg(not(feature = "single_threaded_async"))]
69pub(crate) struct AsyncComputeTaskPoolSender;
70
71#[cfg(not(feature = "single_threaded_async"))]
72impl AsyncComputeTaskPoolSender {
73    /// This is only used to create a task to cancel an existing task, so we
74    /// always detach
75    pub(crate) fn send<F>(&self, f: impl FnOnce() -> F)
76    where
77        F: Future + Send + 'static,
78        F::Output: Send + 'static,
79    {
80        use bevy_tasks::AsyncComputeTaskPool;
81        AsyncComputeTaskPool::get().spawn(f()).detach();
82    }
83}
84
85/// This trait is used as a trait bound that is equivalent to [`Send`] except
86/// when the `single_threaded_async` feature is active, in which case it is no
87/// longer a bound at all because the single threaded async executor does not
88/// require tasks to be [`Send`].
89#[cfg(not(feature = "single_threaded_async"))]
90pub trait Sendish: Send {}
91
92#[cfg(not(feature = "single_threaded_async"))]
93impl<T: Send> Sendish for T {}
94
95/// This trait is used as a trait bound that is equivalent to [`Send`] except
96/// when the `single_threaded_async` feature is active, in which case it is no
97/// longer a bound at all because the single threaded async executor does not
98/// require tasks to be [`Send`].
99#[cfg(feature = "single_threaded_async")]
100pub trait Sendish {}
101
102#[cfg(feature = "single_threaded_async")]
103impl<T> Sendish for T {}