From 24f4421dcc0260686bbae60b5aca9096c49c0774 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Mon, 9 Aug 2021 13:53:32 +0800 Subject: [PATCH 1/3] Make tokio / async-io optional task execution engines behind optional features --- Cargo.toml | 7 ++++++- crates/bevy_asset/Cargo.toml | 3 ++- crates/bevy_asset/src/asset_server.rs | 14 +++++--------- crates/bevy_internal/Cargo.toml | 4 ++++ crates/bevy_tasks/Cargo.toml | 6 +++++- crates/bevy_tasks/src/countdown_event.rs | 11 +++++------ crates/bevy_tasks/src/lib.rs | 4 ++++ crates/bevy_tasks/src/task_pool.rs | 6 +++--- crates/bevy_wgpu/Cargo.toml | 4 +++- crates/bevy_wgpu/src/lib.rs | 3 +-- .../src/renderer/wgpu_render_resource_context.rs | 3 +-- deny.toml | 2 ++ docs/cargo_features.md | 2 ++ examples/async_tasks/async_compute.rs | 2 +- 14 files changed, 44 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d71a7ae47611d..cbda447a9ace5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"] license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/bevyengine/bevy" +resolver = "2" [workspace] exclude = ["benches"] @@ -86,6 +87,10 @@ subpixel_glyph_atlas = ["bevy_internal/subpixel_glyph_atlas"] # enable systems that allow for automated testing on CI bevy_ci_testing = ["bevy_internal/bevy_ci_testing"] +# alternative async executors, defaults to futures-lite +async-io = ["bevy_internal/async-io"] +tokio = ["bevy_internal/tokio"] + [dependencies] bevy_dylib = { path = "crates/bevy_dylib", version = "0.5.0", default-features = false, optional = true } bevy_internal = { path = "crates/bevy_internal", version = "0.5.0", default-features = false } @@ -96,7 +101,7 @@ rand = "0.8.0" ron = "0.6.2" serde = { version = "1", features = ["derive"] } # Needed to poll Task examples -futures-lite = "1.11.3" +futures-lite = "1.12.0" [[example]] name = "hello_world" diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index f9b6bdf6679d8..a57752da6d4a1 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -15,6 +15,8 @@ keywords = ["bevy"] [features] default = ["filesystem_watcher"] filesystem_watcher = ["notify"] +async-io = ["bevy_tasks/async-io"] +tokio = ["bevy_tasks/tokio"] [dependencies] # bevy @@ -46,5 +48,4 @@ js-sys = "0.3" ndk-glue = { version = "0.2" } [dev-dependencies] -futures-lite = "1.4.0" tempfile = "3.2.0" diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index f46b96ed7bf8f..02d7212ded68b 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -7,7 +7,7 @@ use crate::{ use anyhow::Result; use bevy_ecs::system::{Res, ResMut}; use bevy_log::warn; -use bevy_tasks::TaskPool; +use bevy_tasks::{self, TaskPool}; use bevy_utils::{HashMap, Uuid}; use crossbeam_channel::TryRecvError; use parking_lot::{Mutex, RwLock}; @@ -717,8 +717,7 @@ mod test { let path: AssetPath = "file.not-a-real-extension".into(); let handle = asset_server.get_handle_untyped(path.get_id()); - let err = futures_lite::future::block_on(asset_server.load_async(path.clone(), true)) - .unwrap_err(); + let err = bevy_tasks::block_on(asset_server.load_async(path.clone(), true)).unwrap_err(); assert!(match err { AssetServerError::MissingAssetLoader { extensions } => { extensions == ["not-a-real-extension"] @@ -737,8 +736,7 @@ mod test { let path: AssetPath = "an/invalid/path.png".into(); let handle = asset_server.get_handle_untyped(path.get_id()); - let err = futures_lite::future::block_on(asset_server.load_async(path.clone(), true)) - .unwrap_err(); + let err = bevy_tasks::block_on(asset_server.load_async(path.clone(), true)).unwrap_err(); assert!(matches!(err, AssetServerError::AssetIoError(_))); assert_eq!(asset_server.get_load_state(handle), LoadState::Failed); @@ -753,8 +751,7 @@ mod test { let path: AssetPath = "fake.fail".into(); let handle = asset_server.get_handle_untyped(path.get_id()); - let err = futures_lite::future::block_on(asset_server.load_async(path.clone(), true)) - .unwrap_err(); + let err = bevy_tasks::block_on(asset_server.load_async(path.clone(), true)).unwrap_err(); assert!(matches!(err, AssetServerError::AssetLoaderError(_))); assert_eq!(asset_server.get_load_state(handle), LoadState::Failed); @@ -785,8 +782,7 @@ mod test { fn load_asset(path: AssetPath, world: &World) -> HandleUntyped { let asset_server = world.get_resource::().unwrap(); - let id = futures_lite::future::block_on(asset_server.load_async(path.clone(), true)) - .unwrap(); + let id = bevy_tasks::block_on(asset_server.load_async(path.clone(), true)).unwrap(); asset_server.get_handle_untyped(id) } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 64460a5d7e98a..9159c5e3b85bc 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -47,6 +47,10 @@ subpixel_glyph_atlas = ["bevy_text/subpixel_glyph_atlas"] # enable systems that allow for automated testing on CI bevy_ci_testing = ["bevy_app/bevy_ci_testing"] +# alternative async executors, defaults to futures-lite +async-io = ["bevy_tasks/async-io", "bevy_wgpu/async-io"] +tokio = ["bevy_tasks/tokio", "bevy_wgpu/tokio"] + [dependencies] # bevy bevy_app = { path = "../bevy_app", version = "0.5.0" } diff --git a/crates/bevy_tasks/Cargo.toml b/crates/bevy_tasks/Cargo.toml index 876d1482c9087..5a6fa3b5602a2 100644 --- a/crates/bevy_tasks/Cargo.toml +++ b/crates/bevy_tasks/Cargo.toml @@ -14,9 +14,13 @@ license = "MIT OR Apache-2.0" keywords = ["bevy"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +async-io = ["async-global-executor/async-io"] +tokio = ["async-global-executor/tokio"] [dependencies] -futures-lite = "1.4.0" +async-global-executor= { version="2.0.2", default-features = false } +futures-lite = "1.12.0" event-listener = "2.4.0" async-executor = "1.3.0" async-channel = "1.4.2" diff --git a/crates/bevy_tasks/src/countdown_event.rs b/crates/bevy_tasks/src/countdown_event.rs index 9f672fe16ba0b..8b5d8fa22751e 100644 --- a/crates/bevy_tasks/src/countdown_event.rs +++ b/crates/bevy_tasks/src/countdown_event.rs @@ -85,13 +85,14 @@ impl CountdownEvent { #[cfg(test)] mod tests { use super::*; + use crate::block_on; #[test] fn countdown_event_ready_after() { let countdown_event = CountdownEvent::new(2); countdown_event.decrement(); countdown_event.decrement(); - futures_lite::future::block_on(countdown_event.listen()); + block_on(countdown_event.listen()); } #[test] @@ -99,9 +100,7 @@ mod tests { let countdown_event = CountdownEvent::new(2); countdown_event.decrement(); let countdown_event_clone = countdown_event.clone(); - let handle = std::thread::spawn(move || { - futures_lite::future::block_on(countdown_event_clone.listen()) - }); + let handle = std::thread::spawn(move || block_on(countdown_event_clone.listen())); // Pause to give the new thread time to start blocking (ugly hack) std::thread::sleep(instant::Duration::from_millis(100)); @@ -117,7 +116,7 @@ mod tests { // notify all listeners let listener1 = event.listen(); event.notify(std::usize::MAX); - futures_lite::future::block_on(listener1); + block_on(listener1); // If all listeners are notified, the structure should now be cleared. We're free to listen // again @@ -129,6 +128,6 @@ mod tests { // Notify all and verify the remaining listener is notified event.notify(std::usize::MAX); - futures_lite::future::block_on(listener3); + block_on(listener3); } } diff --git a/crates/bevy_tasks/src/lib.rs b/crates/bevy_tasks/src/lib.rs index 08d7dfc42b988..f15c0c9c5816c 100644 --- a/crates/bevy_tasks/src/lib.rs +++ b/crates/bevy_tasks/src/lib.rs @@ -23,6 +23,10 @@ pub use countdown_event::CountdownEvent; mod iter; pub use iter::ParallelIterator; +// re-export block_on so that consumers don't need to explicitly depend on the async engine being used. +// it uses futures-lite by default, async-io and tokio are optional behind features +pub use async_global_executor::block_on; + pub mod prelude { #[doc(hidden)] pub use crate::{ diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index 9331799120583..3562f4f942de2 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -136,7 +136,7 @@ impl TaskPool { .spawn(move || { let shutdown_future = ex.run(shutdown_rx.recv()); // Use unwrap_err because we expect a Closed error - future::block_on(shutdown_future).unwrap_err(); + crate::block_on(shutdown_future).unwrap_err(); }) .expect("Failed to spawn thread.") }) @@ -186,7 +186,7 @@ impl TaskPool { if scope.spawned.is_empty() { Vec::default() } else if scope.spawned.len() == 1 { - vec![future::block_on(&mut scope.spawned[0])] + vec![crate::block_on(&mut scope.spawned[0])] } else { let fut = async move { let mut results = Vec::with_capacity(scope.spawned.len()); @@ -215,7 +215,7 @@ impl TaskPool { // simply calling future::block_on(spawned) would deadlock.) let mut spawned = local_executor.spawn(fut); loop { - if let Some(result) = future::block_on(future::poll_once(&mut spawned)) { + if let Some(result) = crate::block_on(future::poll_once(&mut spawned)) { break result; }; diff --git a/crates/bevy_wgpu/Cargo.toml b/crates/bevy_wgpu/Cargo.toml index 24d4cd5a075c0..af6797cd770b1 100644 --- a/crates/bevy_wgpu/Cargo.toml +++ b/crates/bevy_wgpu/Cargo.toml @@ -15,6 +15,8 @@ keywords = ["bevy"] [features] default = ["bevy_winit"] trace = ["wgpu/trace"] +async-io = ["async-global-executor/async-io"] +tokio = ["async-global-executor/tokio"] [dependencies] # bevy @@ -30,7 +32,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.5.0" } # other wgpu = "0.9" -futures-lite = "1.4.0" crossbeam-channel = "0.5.0" crossbeam-utils = "0.8.1" parking_lot = "0.11.0" +async-global-executor= { version="2.0.2", default-features = false } \ No newline at end of file diff --git a/crates/bevy_wgpu/src/lib.rs b/crates/bevy_wgpu/src/lib.rs index 0adb26dc066f0..874abd6a9de29 100644 --- a/crates/bevy_wgpu/src/lib.rs +++ b/crates/bevy_wgpu/src/lib.rs @@ -15,7 +15,6 @@ use bevy_render::{ renderer::{shared_buffers_update_system, RenderResourceContext, SharedBuffers}, RenderStage, }; -use futures_lite::future; use renderer::WgpuRenderResourceContext; use std::borrow::Cow; @@ -113,7 +112,7 @@ pub fn get_wgpu_render_system(world: &mut World) -> impl FnMut(&mut World) { .get_resource::() .cloned() .unwrap_or_else(WgpuOptions::default); - let mut wgpu_renderer = future::block_on(WgpuRenderer::new(options)); + let mut wgpu_renderer = async_global_executor::block_on(WgpuRenderer::new(options)); let resource_context = WgpuRenderResourceContext::new(wgpu_renderer.device.clone()); world.insert_resource::>(Box::new(resource_context)); diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 8e53d3c292a96..2168e6109f631 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -15,7 +15,6 @@ use bevy_render::{ }; use bevy_utils::tracing::trace; use bevy_window::{Window, WindowId}; -use futures_lite::future; use std::{ borrow::Cow, num::{NonZeroU32, NonZeroU64}, @@ -654,7 +653,7 @@ impl RenderResourceContext for WgpuRenderResourceContext { }; let data = buffer_slice.map_async(wgpu_mode); self.device.poll(wgpu::Maintain::Wait); - if future::block_on(data).is_err() { + if async_global_executor::block_on(data).is_err() { panic!("Failed to map buffer to host."); } } diff --git a/deny.toml b/deny.toml index 663bc6450cd7b..7a1b5fbb25fb2 100644 --- a/deny.toml +++ b/deny.toml @@ -46,6 +46,8 @@ skip = [ { name = "core-graphics", version = "0.19" }, { name = "fixedbitset", version = "0.2" }, { name = "hashbrown", version = "0.9" }, + { name = "jni", version = "0.18.0" }, + { name = "jni", version = "0.19.0" }, { name = "libm", version = "0.1" }, { name = "mach", version = "0.2" }, { name = "ndk", version = "0.2" }, diff --git a/docs/cargo_features.md b/docs/cargo_features.md index b7dd276f2b73d..6f8536e4df025 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -36,3 +36,5 @@ |wayland|Enable this to use Wayland display server protocol other than X11.| |subpixel_glyph_atlas|Enable this to cache glyphs using subpixel accuracy. This increases texture memory usage as each position requires a separate sprite in the glyph atlas, but provide more accurate character spacing.| |bevy_ci_testing|Used for running examples in CI.| +|tokio|Use tokio as task execution engine.| +|async-io|Use async-io as task execution engine.| diff --git a/examples/async_tasks/async_compute.rs b/examples/async_tasks/async_compute.rs index 9e0b50b05a3ea..3933da67b8cfc 100644 --- a/examples/async_tasks/async_compute.rs +++ b/examples/async_tasks/async_compute.rs @@ -81,7 +81,7 @@ fn handle_tasks( box_material_handle: Res, ) { for (entity, mut task) in transform_tasks.iter_mut() { - if let Some(transform) = future::block_on(future::poll_once(&mut *task)) { + if let Some(transform) = bevy::tasks::block_on(future::poll_once(&mut *task)) { // Add our new PbrBundle of components to our tagged entity commands.entity(entity).insert_bundle(PbrBundle { mesh: box_mesh_handle.0.clone(), From a6507ddab31153e2688a0dcd220d62aa9448d127 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Sat, 26 Feb 2022 01:17:16 +0800 Subject: [PATCH 2/3] cleanup --- Cargo.toml | 1 - crates/bevy_crevice/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 21a1a99016556..47da783158a01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"] license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/bevyengine/bevy" -resolver = "2" [workspace] exclude = ["benches", "crates/bevy_ecs_compile_fail_tests"] diff --git a/crates/bevy_crevice/Cargo.toml b/crates/bevy_crevice/Cargo.toml index fe6c6114b2916..8646ab2c4b57b 100644 --- a/crates/bevy_crevice/Cargo.toml +++ b/crates/bevy_crevice/Cargo.toml @@ -10,7 +10,6 @@ repository = "https://github.com/bevyengine/bevy" readme = "README.md" keywords = ["glsl", "std140", "std430"] license = "MIT OR Apache-2.0" -# resolver = "2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 586d55a1c22f22c4a7e0796a518fa408e4e411ec Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Sat, 26 Feb 2022 01:25:09 +0800 Subject: [PATCH 3/3] fix bad merge --- crates/bevy_tasks/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_tasks/src/lib.rs b/crates/bevy_tasks/src/lib.rs index d85bb45cbc96e..f3dc80caaaa15 100644 --- a/crates/bevy_tasks/src/lib.rs +++ b/crates/bevy_tasks/src/lib.rs @@ -26,11 +26,11 @@ pub use countdown_event::CountdownEvent; mod iter; pub use iter::ParallelIterator; -#[allow(missing_docs)] // re-export block_on so that consumers don't need to explicitly depend on the async engine being used. // it uses futures-lite by default, async-io and tokio are optional behind features pub use async_global_executor::block_on; +#[allow(missing_docs)] pub mod prelude { #[doc(hidden)] pub use crate::{