Coverage Report

Created: 2025-07-11 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.16/src/lazy.rs
Line
Count
Source (jump to first uncovered line)
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 {
24
0
    pub const fn new() -> Self {
25
0
        Self(AtomicUsize::new(Self::UNINIT))
26
0
    }
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.
34
0
    pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize {
35
0
        // Relaxed ordering is fine, as we only have a single atomic variable.
36
0
        let mut val = self.0.load(Relaxed);
37
0
        if val == Self::UNINIT {
38
0
            val = init();
39
0
            self.0.store(val, Relaxed);
40
0
        }
41
0
        val
42
0
    }
43
}
44
45
// Identical to LazyUsize except with bool instead of usize.
46
pub(crate) struct LazyBool(LazyUsize);
47
48
impl LazyBool {
49
0
    pub const fn new() -> Self {
50
0
        Self(LazyUsize::new())
51
0
    }
52
53
0
    pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {
54
0
        self.0.unsync_init(|| init() as usize) != 0
55
0
    }
56
}