Improve ergonomics of platform_support
's Instant
(#17577)
# Objective
- Make working with `bevy_time` more ergonomic in `no_std` environments.
Currently `bevy_time` expects the getter in environments where time
can't be obtained automatically via the instruction set or the standard
library to be of type `*mut fn() -> Duration`.
[`fn()`](https://doc.rust-lang.org/beta/std/primitive.fn.html) is
already a function pointer, so `*mut fn()` is a _pointer to a function
pointer_. This is harder to use and error prone since creating a pointer
out of something like `&mut fn() -> Duration` when the lifetime of the
reference isn't static will lead to an undefined behavior once the
reference is freed
## Solution
- Accept a `fn() -> Duration` instead
## Testing
- I made a whole game on the Playdate that relies on `bevy_time`
heavily, see:
[bevydate_time](1b4f02adcd/src/lib.rs (L510-L546)
)
for usage of the Instant's getter.
---
## Showcase
<details>
<summary>Click to view showcase</summary>
https://github.com/user-attachments/assets/f687847f-6b62-4322-95f3-c908ada3db30
</details>
## Migration Guide
This is a breaking change but it's not for people coming from Bevy v0.15
### Small thank you note
Thanks to my friend https://github.com/repnop for helping me understand
how to deal with function pointers in `unsafe` environments
Co-authored-by: Wesley Norris <repnop@repnop.dev>
This commit is contained in:
parent
9165fb020a
commit
469b218f20
@ -30,7 +30,7 @@ mod fallback {
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
static ELAPSED_GETTER: AtomicPtr<fn() -> Duration> = AtomicPtr::new(unset_getter as *mut _);
|
||||
static ELAPSED_GETTER: AtomicPtr<()> = AtomicPtr::new(unset_getter as *mut _);
|
||||
|
||||
/// Fallback implementation of `Instant` suitable for a `no_std` environment.
|
||||
///
|
||||
@ -53,7 +53,7 @@ mod fallback {
|
||||
let getter = ELAPSED_GETTER.load(Ordering::Acquire);
|
||||
|
||||
// SAFETY: Function pointer is always valid
|
||||
let getter = unsafe { *getter };
|
||||
let getter = unsafe { core::mem::transmute::<_, fn() -> Duration>(getter) };
|
||||
|
||||
Self((getter)())
|
||||
}
|
||||
@ -66,8 +66,8 @@ mod fallback {
|
||||
/// - The function provided must accurately represent the elapsed time.
|
||||
/// - The function must preserve all invariants of the [`Instant`] type.
|
||||
/// - The pointer to the function must be valid whenever [`Instant::now`] is called.
|
||||
pub unsafe fn set_elapsed(getter: *mut fn() -> Duration) {
|
||||
ELAPSED_GETTER.store(getter, Ordering::Release);
|
||||
pub unsafe fn set_elapsed(getter: fn() -> Duration) {
|
||||
ELAPSED_GETTER.store(getter as *mut _, Ordering::Release);
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
|
Loading…
Reference in New Issue
Block a user