Add portable-atomic
support to bevy_utils
for once!
(#17027)
# Objective - Improves platform compatibility for `bevy_utils` ## Solution - Added `portable-atomic` to allow using the `once!` macro on more platforms (e.g., Raspberry Pi Pico) ## Testing - CI ## Notes - This change should be entirely hidden thanks to the use of `doc(hidden)`. Enabling the new `portable-atomic` feature just allows using the `once!` macro on platforms which previously could not. - I took the liberty of updating the feature documentation to be more in line with how I've documented features in `bevy_ecs`/`bevy_app`/etc. for their `no_std` updates.
This commit is contained in:
parent
ad9f946201
commit
c8110f5f86
@ -10,12 +10,39 @@ keywords = ["bevy"]
|
||||
|
||||
[features]
|
||||
default = ["std", "serde", "tracing"]
|
||||
std = ["alloc", "tracing?/std", "foldhash/std", "dep:thread_local"]
|
||||
alloc = ["hashbrown"]
|
||||
detailed_trace = []
|
||||
|
||||
# Functionality
|
||||
|
||||
## Adds serialization support through `serde`.
|
||||
serde = ["hashbrown/serde"]
|
||||
|
||||
# Debugging Features
|
||||
|
||||
## Enables `tracing` integration, allowing spans and other metrics to be reported
|
||||
## through that framework.
|
||||
tracing = ["dep:tracing"]
|
||||
|
||||
## Enables more detailed reporting via `tracing`.
|
||||
detailed_trace = ["tracing"]
|
||||
|
||||
# Platform Compatibility
|
||||
|
||||
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
||||
## on `no_std` targets, but provides access to certain additional features on
|
||||
## supported platforms.
|
||||
std = ["alloc", "tracing?/std", "foldhash/std", "dep:thread_local"]
|
||||
|
||||
## Allows access to the `alloc` crate.
|
||||
alloc = ["hashbrown"]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = ["portable-atomic?/critical-section"]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = ["dep:portable-atomic"]
|
||||
|
||||
[dependencies]
|
||||
foldhash = { version = "0.1.3", default-features = false }
|
||||
tracing = { version = "0.1", default-features = false, optional = true }
|
||||
@ -24,6 +51,9 @@ hashbrown = { version = "0.15.1", features = [
|
||||
"raw-entry",
|
||||
], optional = true, default-features = false }
|
||||
thread_local = { version = "1.0", optional = true }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
static_assertions = "1.1.0"
|
||||
|
@ -34,6 +34,9 @@ mod once;
|
||||
mod parallel_queue;
|
||||
mod time;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use once::OnceFlag;
|
||||
|
||||
/// For when you want a deterministic hasher.
|
||||
///
|
||||
/// Seed was randomly generated with a fair dice roll. Guaranteed to be random:
|
||||
|
@ -1,11 +1,38 @@
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// Wrapper around an [`AtomicBool`], abstracting the backing implementation and
|
||||
/// ordering considerations.
|
||||
#[doc(hidden)]
|
||||
pub struct OnceFlag(AtomicBool);
|
||||
|
||||
impl OnceFlag {
|
||||
/// Create a new flag in the unset state.
|
||||
pub const fn new() -> Self {
|
||||
Self(AtomicBool::new(true))
|
||||
}
|
||||
|
||||
/// Sets this flag. Will return `true` if this flag hasn't been set before.
|
||||
pub fn set(&self) -> bool {
|
||||
self.0.swap(false, Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OnceFlag {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Call some expression only once per call site.
|
||||
#[macro_export]
|
||||
macro_rules! once {
|
||||
($expression:expr) => {{
|
||||
use ::core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
static SHOULD_FIRE: AtomicBool = AtomicBool::new(true);
|
||||
if SHOULD_FIRE.swap(false, Ordering::Relaxed) {
|
||||
static SHOULD_FIRE: $crate::OnceFlag = $crate::OnceFlag::new();
|
||||
if SHOULD_FIRE.set() {
|
||||
$expression;
|
||||
}
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user