Create new NonSendMarker
(#18301)
# Objective Create new `NonSendMarker` that does not depend on `NonSend`. Required, in order to accomplish #17682. In that issue, we are trying to replace `!Send` resources with `thread_local!` in order to unblock the resources-as-components effort. However, when we remove all the `!Send` resources from a system, that allows the system to run on a thread other than the main thread, which is against the design of the system. So this marker gives us the control to require a system to run on the main thread without depending on `!Send` resources. ## Solution Create a new `NonSendMarker` to replace the existing one that does not depend on `NonSend`. ## Testing Other than running tests, I ran a few examples: - `window_resizing` - `wireframe` - `volumetric_fog` (looks so cool) - `rotation` - `button` There is a Mac/iOS-specific change and I do not have a Mac or iOS device to test it. I am doubtful that it would cause any problems for 2 reasons: 1. The change is the same as the non-wasm change which I did test 2. The Pixel Eagle tests run Mac tests But it wouldn't hurt if someone wanted to spin up an example that utilizes the `bevy_render` crate, which is where the Mac/iSO change was. ## Migration Guide If `NonSendMarker` is being used from `bevy_app::prelude::*`, replace it with `bevy_ecs::system::NonSendMarker` or use it from `bevy_ecs::prelude::*`. In addition to that, `NonSendMarker` does not need to be wrapped like so: ```rust fn my_system(_non_send_marker: Option<NonSend<NonSendMarker>>) { ... } ``` Instead, it can be used without any wrappers: ```rust fn my_system(_non_send_marker: NonSendMarker) { ... } ``` --------- Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
This commit is contained in:
parent
694db96ab8
commit
8d9f948684
@ -58,6 +58,6 @@ pub mod prelude {
|
||||
RunFixedMainLoopSystem, SpawnScene, Startup, Update,
|
||||
},
|
||||
sub_app::SubApp,
|
||||
NonSendMarker, Plugin, PluginGroup, TaskPoolOptions, TaskPoolPlugin,
|
||||
Plugin, PluginGroup, TaskPoolOptions, TaskPoolPlugin,
|
||||
};
|
||||
}
|
||||
|
@ -3,18 +3,19 @@ use crate::{App, Plugin};
|
||||
use alloc::string::ToString;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use core::fmt::Debug;
|
||||
use log::trace;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(all(target_arch = "wasm32", feature = "web")))] {
|
||||
use {crate::Last, bevy_ecs::prelude::NonSend, bevy_tasks::tick_global_task_pools_on_main_thread};
|
||||
use {crate::Last, bevy_tasks::tick_global_task_pools_on_main_thread};
|
||||
use bevy_ecs::system::NonSendMarker;
|
||||
|
||||
/// A system used to check and advanced our task pools.
|
||||
///
|
||||
/// Calls [`tick_global_task_pools_on_main_thread`],
|
||||
/// and uses [`NonSendMarker`] to ensure that this system runs on the main thread
|
||||
fn tick_global_task_pools(_main_thread_marker: Option<NonSend<NonSendMarker>>) {
|
||||
fn tick_global_task_pools(_main_thread_marker: NonSendMarker) {
|
||||
tick_global_task_pools_on_main_thread();
|
||||
}
|
||||
}
|
||||
@ -36,8 +37,6 @@ impl Plugin for TaskPoolPlugin {
|
||||
_app.add_systems(Last, tick_global_task_pools);
|
||||
}
|
||||
}
|
||||
/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.
|
||||
pub struct NonSendMarker(PhantomData<*mut ()>);
|
||||
|
||||
/// Defines a simple way to determine how many threads to use given the number of remaining cores
|
||||
/// and number of total cores
|
||||
|
@ -91,8 +91,8 @@ pub mod prelude {
|
||||
spawn::{Spawn, SpawnRelated},
|
||||
system::{
|
||||
Command, Commands, Deferred, EntityCommand, EntityCommands, In, InMut, InRef,
|
||||
IntoSystem, Local, NonSend, NonSendMut, ParamSet, Populated, Query, ReadOnlySystem,
|
||||
Res, ResMut, Single, System, SystemIn, SystemInput, SystemParamBuilder,
|
||||
IntoSystem, Local, NonSend, NonSendMarker, NonSendMut, ParamSet, Populated, Query,
|
||||
ReadOnlySystem, Res, ResMut, Single, System, SystemIn, SystemInput, SystemParamBuilder,
|
||||
SystemParamFunction, WithParamWarnPolicy,
|
||||
},
|
||||
world::{
|
||||
|
@ -1420,6 +1420,33 @@ unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.
|
||||
pub struct NonSendMarker;
|
||||
|
||||
// SAFETY: No world access.
|
||||
unsafe impl SystemParam for NonSendMarker {
|
||||
type State = ();
|
||||
type Item<'w, 's> = Self;
|
||||
|
||||
#[inline]
|
||||
fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
|
||||
system_meta.set_non_send();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param<'world, 'state>(
|
||||
_state: &'state mut Self::State,
|
||||
_system_meta: &SystemMeta,
|
||||
_world: UnsafeWorldCell<'world>,
|
||||
_change_tick: Tick,
|
||||
) -> Self::Item<'world, 'state> {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Does not read any world state
|
||||
unsafe impl ReadOnlySystemParam for NonSendMarker {}
|
||||
|
||||
/// Shared borrow of a non-[`Send`] resource.
|
||||
///
|
||||
/// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the
|
||||
|
@ -304,9 +304,7 @@ const DEFAULT_DESIRED_MAXIMUM_FRAME_LATENCY: u32 = 2;
|
||||
pub fn create_surfaces(
|
||||
// By accessing a NonSend resource, we tell the scheduler to put this system on the main thread,
|
||||
// which is necessary for some OS's
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))] _marker: Option<
|
||||
NonSend<bevy_app::NonSendMarker>,
|
||||
>,
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))] _marker: NonSendMarker,
|
||||
windows: Res<ExtractedWindows>,
|
||||
mut window_surfaces: ResMut<WindowSurfaces>,
|
||||
render_instance: Res<RenderInstance>,
|
||||
|
Loading…
Reference in New Issue
Block a user