Skip to content

Commit 7925e03

Browse files
bushrat011899mockersf
authored andcommitted
Add sleep based on spin to bevy_platform_support (#18633)
# Objective - Fixes #18617 ## Solution - Added `thread::sleep` to `bevy_platform_support` using a spin-based fallback. - Fixed bug in `bevy_platform_support::time::Instant::elapsed` (comparison was backwards) - Switched `ScheduleRunnerPlugin` to use `bevy_platform_support::thread::sleep` on `std` and `no_std` platforms (WASM + Browser excluded) ## Testing - Ran reproduction code from @mockersf in linked issue and confirmed a consistent 60 counts per `println!`. --- ## Notes - I chose to add `bevy_platform_support::thread::sleep` instead of putting the fix in-line within `ScheduleRunnerPlugin` to keep the separation of concerns clean. `sleep` is only used in one other location in Bevy, `bevy_asset`, but I have decided to leave that as-is since `bevy_asset` isn't `no_std` compatible anyway. - The bug in `bevy_platform_support::time::Instant::elapsed` wasn't the cause of this issue, but it did prevent this fix from working so I have included the it in this PR.
1 parent bdfd7a3 commit 7925e03

File tree

4 files changed

+33
-4
lines changed

4 files changed

+33
-4
lines changed

crates/bevy_app/src/schedule_runner.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,8 @@ impl Plugin for ScheduleRunnerPlugin {
159159
} else {
160160
loop {
161161
match tick(&mut app, wait) {
162-
Ok(Some(_delay)) => {
163-
#[cfg(feature = "std")]
164-
std::thread::sleep(_delay);
162+
Ok(Some(delay)) => {
163+
bevy_platform_support::thread::sleep(delay);
165164
}
166165
Ok(None) => continue,
167166
Err(exit) => return exit,

crates/bevy_platform_support/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern crate alloc;
1717

1818
pub mod hash;
1919
pub mod sync;
20+
pub mod thread;
2021
pub mod time;
2122

2223
#[cfg(feature = "alloc")]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Provides `sleep` for all platforms.
2+
3+
pub use thread::sleep;
4+
5+
cfg_if::cfg_if! {
6+
// TODO: use browser timeouts based on ScheduleRunnerPlugin::build
7+
if #[cfg(feature = "std")] {
8+
use std::thread;
9+
} else {
10+
mod fallback {
11+
use core::{hint::spin_loop, time::Duration};
12+
13+
use crate::time::Instant;
14+
15+
/// Puts the current thread to sleep for at least the specified amount of time.
16+
///
17+
/// As this is a `no_std` fallback implementation, this will spin the current thread.
18+
pub fn sleep(dur: Duration) {
19+
let start = Instant::now();
20+
21+
while start.elapsed() < dur {
22+
spin_loop()
23+
}
24+
}
25+
}
26+
27+
use fallback as thread;
28+
}
29+
}

crates/bevy_platform_support/src/time/fallback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl Instant {
8080
/// Returns the amount of time elapsed since this instant.
8181
#[must_use]
8282
pub fn elapsed(&self) -> Duration {
83-
self.saturating_duration_since(Instant::now())
83+
Instant::now().saturating_duration_since(*self)
8484
}
8585

8686
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as

0 commit comments

Comments
 (0)