Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/bevy_diagnostic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ keywords = ["bevy"]
# Disables diagnostics that are unsupported when Bevy is dynamically linked
dynamic_linking = []
sysinfo_plugin = ["sysinfo"]
multi_threaded = []

[dependencies]
# bevy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ pub mod internal {

use bevy_app::{App, First, Startup, Update};
use bevy_ecs::system::Resource;
use bevy_tasks::{available_parallelism, block_on, poll_once, AsyncComputeTaskPool, Task};
#[cfg(not(feature = "multi_threaded"))]
use bevy_tasks::FakeTask;
use bevy_tasks::{available_parallelism, AsyncComputeTaskPool};
#[cfg(feature = "multi_threaded")]
use bevy_tasks::{block_on, poll_once, Task};

use bevy_utils::tracing::info;
use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System};

Expand Down Expand Up @@ -98,7 +103,10 @@ pub mod internal {

#[derive(Resource, Default)]
struct SysinfoTasks {
#[cfg(feature = "multi_threaded")]
tasks: Vec<Task<SysinfoRefreshData>>,
#[cfg(not(feature = "multi_threaded"))]
tasks: Vec<FakeTask<SysinfoRefreshData>>,
}

fn launch_diagnostic_tasks(
Expand Down Expand Up @@ -151,9 +159,12 @@ pub mod internal {

fn read_diagnostic_tasks(mut diagnostics: Diagnostics, mut tasks: ResMut<SysinfoTasks>) {
tasks.tasks.retain_mut(|task| {
#[cfg(feature = "multi_threaded")]
let Some(data) = block_on(poll_once(task)) else {
return true;
};
#[cfg(not(feature = "multi_threaded"))]
let data = &task.result;

diagnostics.add_measurement(&SystemInformationDiagnosticsPlugin::CPU_USAGE, || {
data.current_cpu_usage
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ multi_threaded = [
"bevy_ecs/multi_threaded",
"bevy_render?/multi_threaded",
"bevy_tasks/multi_threaded",
"bevy_diagnostic/multi_threaded",
]
async-io = ["bevy_tasks/async-io"]

Expand Down
61 changes: 51 additions & 10 deletions crates/bevy_tasks/src/single_threaded_task_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,28 +150,51 @@ impl TaskPool {
/// end-user.
///
/// If the provided future is non-`Send`, [`TaskPool::spawn_local`] should be used instead.
#[cfg(not(target_arch = "wasm32"))]
pub fn spawn<T>(&self, future: impl Future<Output = T> + 'static) -> FakeTask<T>
where
T: 'static,
{
LOCAL_EXECUTOR.with(|executor| {
let task = executor.spawn(future);
// Loop until all tasks are done
while executor.try_tick() {}

FakeTask {
// task should be ready
result: crate::block_on(task),
}
})
}

/// Spawns a static future onto the thread pool. The returned Task is a future. It can also be
/// cancelled and "detached" allowing it to continue running without having to be polled by the
/// end-user.
///
/// If the provided future is non-`Send`, [`TaskPool::spawn_local`] should be used instead.
#[cfg(target_arch = "wasm32")]
pub fn spawn<T>(&self, future: impl Future<Output = T> + 'static) -> FakeTask
where
T: 'static,
{
#[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(async move {
future.await;
});

#[cfg(not(target_arch = "wasm32"))]
{
LOCAL_EXECUTOR.with(|executor| {
let _task = executor.spawn(future);
// Loop until all tasks are done
while executor.try_tick() {}
});
}

FakeTask
}

/// Spawns a static future on the JS event loop. This is exactly the same as [`TaskPool::spawn`].
#[cfg(not(target_arch = "wasm32"))]
pub fn spawn_local<T>(&self, future: impl Future<Output = T> + 'static) -> FakeTask<T>
where
T: 'static,
{
self.spawn(future)
}

/// Spawns a static future on the JS event loop. This is exactly the same as [`TaskPool::spawn`].
#[cfg(target_arch = "wasm32")]
pub fn spawn_local<T>(&self, future: impl Future<Output = T> + 'static) -> FakeTask
where
T: 'static,
Expand Down Expand Up @@ -202,8 +225,26 @@ impl TaskPool {
///
/// This does nothing and is therefore safe, and recommended, to ignore.
#[derive(Debug)]
#[cfg(not(target_arch = "wasm32"))]
pub struct FakeTask<T> {
/// In case of not wasm arch contains result of future execution
pub result: T,
}

#[cfg(not(target_arch = "wasm32"))]
impl<T> FakeTask<T> {
/// No op on the single threaded task pool
pub fn detach(self) {}
}

/// An empty task used in single-threaded contexts.
///
/// This does nothing and is therefore safe, and recommended, to ignore.
#[derive(Debug)]
#[cfg(target_arch = "wasm32")]
pub struct FakeTask;

#[cfg(target_arch = "wasm32")]
impl FakeTask {
/// No op on the single threaded task pool
pub fn detach(self) {}
Expand Down