1 use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; 2 3 // This structure represents a lazily initialized static usize value. Useful 4 // when it is preferable to just rerun initialization instead of locking. 5 // unsync_init will invoke an init() function until it succeeds, then return the 6 // cached value for future calls. 7 // 8 // unsync_init supports init() "failing". If the init() method returns UNINIT, 9 // that value will be returned as normal, but will not be cached. 10 // 11 // Users should only depend on the _value_ returned by init() functions. 12 // Specifically, for the following init() function: 13 // fn init() -> usize { 14 // a(); 15 // let v = b(); 16 // c(); 17 // v 18 // } 19 // the effects of c() or writes to shared memory will not necessarily be 20 // observed and additional synchronization methods may be needed. 21 pub(crate) struct LazyUsize(AtomicUsize); 22 23 impl LazyUsize { new() -> Self24 pub const fn new() -> Self { 25 Self(AtomicUsize::new(Self::UNINIT)) 26 } 27 28 // The initialization is not completed. 29 pub const UNINIT: usize = usize::max_value(); 30 31 // Runs the init() function at most once, returning the value of some run of 32 // init(). Multiple callers can run their init() functions in parallel. 33 // init() should always return the same value, if it succeeds. unsync_init(&self, init: impl FnOnce() -> usize) -> usize34 pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize { 35 // Relaxed ordering is fine, as we only have a single atomic variable. 36 let mut val = self.0.load(Relaxed); 37 if val == Self::UNINIT { 38 val = init(); 39 self.0.store(val, Relaxed); 40 } 41 val 42 } 43 } 44 45 // Identical to LazyUsize except with bool instead of usize. 46 pub(crate) struct LazyBool(LazyUsize); 47 48 impl LazyBool { new() -> Self49 pub const fn new() -> Self { 50 Self(LazyUsize::new()) 51 } 52 unsync_init(&self, init: impl FnOnce() -> bool) -> bool53 pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool { 54 self.0.unsync_init(|| init() as usize) != 0 55 } 56 } 57