naga/
racy_lock.rs

1#[cfg(no_std)]
2use alloc::boxed::Box;
3#[cfg(no_std)]
4use once_cell::race::OnceBox;
5#[cfg(std)]
6use std::sync::LazyLock;
7
8#[cfg(std)]
9type Inner<T> = LazyLock<T, fn() -> T>;
10#[cfg(no_std)]
11type Inner<T> = OnceBox<T>;
12
13/// Lazy static helper that uses [`LazyLock`] with `std` and [`OnceBox`] otherwise.
14///
15/// [`LazyLock`]: https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html
16/// [`OnceBox`]: https://docs.rs/once_cell/latest/once_cell/race/struct.OnceBox.html
17#[derive(Debug)]
18pub struct RacyLock<T: 'static> {
19    inner: Inner<T>,
20    #[cfg(no_std)]
21    init: fn() -> T,
22}
23
24impl<T: 'static> RacyLock<T> {
25    #[cfg(std)]
26    /// Creates a new [`RacyLock`], which will initialize using the provided `init` function.
27    pub const fn new(init: fn() -> T) -> Self {
28        Self {
29            inner: LazyLock::new(init),
30        }
31    }
32
33    #[cfg(no_std)]
34    /// Creates a new [`RacyLock`], which will initialize using the provided `init` function.
35    pub const fn new(init: fn() -> T) -> Self {
36        Self {
37            inner: OnceBox::new(),
38            init,
39        }
40    }
41}
42
43#[cfg(std)]
44impl<T: 'static> core::ops::Deref for RacyLock<T> {
45    type Target = T;
46
47    /// Loads the internal value, initializing it if required.
48    fn deref(&self) -> &Self::Target {
49        &self.inner
50    }
51}
52
53#[cfg(no_std)]
54impl<T: 'static> core::ops::Deref for RacyLock<T> {
55    type Target = T;
56
57    /// Loads the internal value, initializing it if required.
58    fn deref(&self) -> &Self::Target {
59        self.inner.get_or_init(|| Box::new((self.init)()))
60    }
61}