1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
//! Synchronized one-time and lazy initialization primitives that use spin-locks //! in case of concurrent accesses under contention. use core::sync::atomic::{spin_loop_hint, Ordering}; use crate::cell::{Block, Unblock}; use crate::state::{AtomicOnceState, BlockedState, OnceState::WouldBlock}; use crate::POISON_PANIC_MSG; use self::internal::Spin; //////////////////////////////////////////////////////////////////////////////////////////////////// // Lazy (type alias) //////////////////////////////////////////////////////////////////////////////////////////////////// /// A type for lazy initialization of e.g. global static variables, which /// provides the same functionality as the `lazy_static!` macro. /// /// This type uses spin-locks if the initialization is contended and is thus /// `#[no_std]` compatible. /// /// For the API of this type alias, see the API of the generic /// [`Lazy`](crate::doc::Lazy) type. pub type Lazy<T, F = fn() -> T> = crate::lazy::Lazy<T, Spin, F>; //////////////////////////////////////////////////////////////////////////////////////////////////// // OnceCell (type alias) //////////////////////////////////////////////////////////////////////////////////////////////////// /// An interior mutability cell type which allows synchronized one-time /// initialization and read-only access exclusively after initialization. /// /// This type uses spin-locks if the initialization is contended and is thus /// `#[no_std]` compatible. /// /// For the API of this type alias, see the generic /// [`OnceCell`](crate::doc::OnceCell) type. pub type OnceCell<T> = crate::cell::OnceCell<T, Spin>; //////////////////////////////////////////////////////////////////////////////////////////////////// // Once (type alias) //////////////////////////////////////////////////////////////////////////////////////////////////// /// A synchronization primitive which can be used to run a one-time global /// initialization. /// /// This type uses spin-locks if the initialization is contended and is thus /// `#[no_std]` compatible. /// /// For the API of this type alias, see the generic /// [`OnceCell`](crate::doc::OnceCell) type. /// This is a specialization with `T = ()`. pub type Once = OnceCell<()>; //////////////////////////////////////////////////////////////////////////////////////////////////// // Spin //////////////////////////////////////////////////////////////////////////////////////////////////// mod internal { /// Blocking strategy for blocking threads using spin-locks. #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct Spin; } /********** impl Unblock **************************************************************************/ unsafe impl Unblock for Spin { #[inline(always)] unsafe fn on_unblock(_: BlockedState) {} } /********** impl Block ****************************************************************************/ unsafe impl Block for Spin { /// Spins until the [`OnceCell`] state is set to `READY`, or panics if it /// becomes poisoned. #[inline] fn block(state: &AtomicOnceState) { // (spin:1) this acquire load syncs-with the acq-rel swap (guard:2) while let WouldBlock(_) = state.load(Ordering::Acquire).expect(POISON_PANIC_MSG) { spin_loop_hint() } } } #[cfg(test)] mod tests { generate_tests_non_blocking!(); generate_tests!(); }