Use new run_without_applying_deferred
method in SingleThreadedExecutor
(#18684)
# Objective Simplify code in the `SingleThreadedExecutor` by removing a special case for exclusive systems. The `SingleThreadedExecutor` runs systems without immediately applying deferred buffers. That required calling `run_unsafe()` instead of `run()`, but that would `panic` for exclusive systems, so the code also needed a special case for those. Following #18076 and #18406, we have a `run_without_applying_deferred` method that has the exact behavior we want and works on exclusive systems. ## Solution Replace the code in `SingleThreadedExecutor` that runs systems with a single call to `run_without_applying_deferred()`. Also add this as a wrapper in the `__rust_begin_short_backtrace` module to preserve the special behavior for backtraces.
This commit is contained in:
parent
49f1827633
commit
3442e2556d
@ -271,38 +271,54 @@ impl IntoSystemSet<()> for ApplyDeferred {
|
|||||||
mod __rust_begin_short_backtrace {
|
mod __rust_begin_short_backtrace {
|
||||||
use core::hint::black_box;
|
use core::hint::black_box;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use crate::world::unsafe_world_cell::UnsafeWorldCell;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Result,
|
error::Result,
|
||||||
system::{ReadOnlySystem, ScheduleSystem},
|
system::{ReadOnlySystem, ScheduleSystem},
|
||||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// See `System::run_unsafe`.
|
/// See `System::run_unsafe`.
|
||||||
|
// This is only used by `MultiThreadedExecutor`, and would be dead code without `std`.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub(super) unsafe fn run_unsafe(system: &mut ScheduleSystem, world: UnsafeWorldCell) -> Result {
|
pub(super) unsafe fn run_unsafe(system: &mut ScheduleSystem, world: UnsafeWorldCell) -> Result {
|
||||||
let result = system.run_unsafe((), world);
|
let result = system.run_unsafe((), world);
|
||||||
|
// Call `black_box` to prevent this frame from being tail-call optimized away
|
||||||
black_box(());
|
black_box(());
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// See `ReadOnlySystem::run_unsafe`.
|
/// See `ReadOnlySystem::run_unsafe`.
|
||||||
#[cfg_attr(
|
// This is only used by `MultiThreadedExecutor`, and would be dead code without `std`.
|
||||||
not(feature = "std"),
|
#[cfg(feature = "std")]
|
||||||
expect(dead_code, reason = "currently only used with the std feature")
|
|
||||||
)]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub(super) unsafe fn readonly_run_unsafe<O: 'static>(
|
pub(super) unsafe fn readonly_run_unsafe<O: 'static>(
|
||||||
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
|
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
|
||||||
world: UnsafeWorldCell,
|
world: UnsafeWorldCell,
|
||||||
) -> O {
|
) -> O {
|
||||||
|
// Call `black_box` to prevent this frame from being tail-call optimized away
|
||||||
black_box(system.run_unsafe((), world))
|
black_box(system.run_unsafe((), world))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub(super) fn run(system: &mut ScheduleSystem, world: &mut World) -> Result {
|
pub(super) fn run(system: &mut ScheduleSystem, world: &mut World) -> Result {
|
||||||
let result = system.run((), world);
|
let result = system.run((), world);
|
||||||
|
// Call `black_box` to prevent this frame from being tail-call optimized away
|
||||||
|
black_box(());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub(super) fn run_without_applying_deferred(
|
||||||
|
system: &mut ScheduleSystem,
|
||||||
|
world: &mut World,
|
||||||
|
) -> Result {
|
||||||
|
let result = system.run_without_applying_deferred((), world);
|
||||||
|
// Call `black_box` to prevent this frame from being tail-call optimized away
|
||||||
black_box(());
|
black_box(());
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -312,6 +328,7 @@ mod __rust_begin_short_backtrace {
|
|||||||
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
|
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
|
||||||
world: &mut World,
|
world: &mut World,
|
||||||
) -> O {
|
) -> O {
|
||||||
|
// Call `black_box` to prevent this frame from being tail-call optimized away
|
||||||
black_box(system.run((), world))
|
black_box(system.run((), world))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,33 +128,16 @@ impl SystemExecutor for SingleThreadedExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let f = AssertUnwindSafe(|| {
|
let f = AssertUnwindSafe(|| {
|
||||||
if system.is_exclusive() {
|
if let Err(err) =
|
||||||
if let Err(err) = __rust_begin_short_backtrace::run(system, world) {
|
__rust_begin_short_backtrace::run_without_applying_deferred(system, world)
|
||||||
error_handler(
|
{
|
||||||
err,
|
error_handler(
|
||||||
ErrorContext::System {
|
err,
|
||||||
name: system.name(),
|
ErrorContext::System {
|
||||||
last_run: system.get_last_run(),
|
name: system.name(),
|
||||||
},
|
last_run: system.get_last_run(),
|
||||||
);
|
},
|
||||||
}
|
);
|
||||||
} else {
|
|
||||||
// Use run_unsafe to avoid immediately applying deferred buffers
|
|
||||||
let world = world.as_unsafe_world_cell();
|
|
||||||
system.update_archetype_component_access(world);
|
|
||||||
// SAFETY: We have exclusive, single-threaded access to the world and
|
|
||||||
// update_archetype_component_access is being called immediately before this.
|
|
||||||
unsafe {
|
|
||||||
if let Err(err) = __rust_begin_short_backtrace::run_unsafe(system, world) {
|
|
||||||
error_handler(
|
|
||||||
err,
|
|
||||||
ErrorContext::System {
|
|
||||||
name: system.name(),
|
|
||||||
last_run: system.get_last_run(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user