Coverage Report

Created: 2025-12-31 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.2.7/src/util.rs
Line
Count
Source
1
// Copyright 2019 Developers of the Rand project.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
#![allow(dead_code)]
9
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
10
11
// This structure represents a lazily initialized static usize value. Useful
12
// when it is preferable to just rerun initialization instead of locking.
13
// Both unsync_init and sync_init will invoke an init() function until it
14
// succeeds, then return the cached value for future calls.
15
//
16
// Both methods support init() "failing". If the init() method returns UNINIT,
17
// that value will be returned as normal, but will not be cached.
18
//
19
// Users should only depend on the _value_ returned by init() functions.
20
// Specifically, for the following init() function:
21
//      fn init() -> usize {
22
//          a();
23
//          let v = b();
24
//          c();
25
//          v
26
//      }
27
// the effects of c() or writes to shared memory will not necessarily be
28
// observed and additional synchronization methods with be needed.
29
pub struct LazyUsize(AtomicUsize);
30
31
impl LazyUsize {
32
0
    pub const fn new() -> Self {
33
0
        Self(AtomicUsize::new(Self::UNINIT))
34
0
    }
35
36
    // The initialization is not completed.
37
    pub const UNINIT: usize = usize::max_value();
38
39
    // Runs the init() function at least once, returning the value of some run
40
    // of init(). Multiple callers can run their init() functions in parallel.
41
    // init() should always return the same value, if it succeeds.
42
0
    pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize {
43
        // Relaxed ordering is fine, as we only have a single atomic variable.
44
0
        let mut val = self.0.load(Relaxed);
45
0
        if val == Self::UNINIT {
46
0
            val = init();
47
0
            self.0.store(val, Relaxed);
48
0
        }
49
0
        val
50
0
    }
51
}
52
53
// Identical to LazyUsize except with bool instead of usize.
54
pub struct LazyBool(LazyUsize);
55
56
impl LazyBool {
57
0
    pub const fn new() -> Self {
58
0
        Self(LazyUsize::new())
59
0
    }
60
61
0
    pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {
62
0
        self.0.unsync_init(|| init() as usize) != 0
63
0
    }
64
}