|
6 | 6 | // option. This file may not be copied, modified, or distributed |
7 | 7 | // except according to those terms. |
8 | 8 | #![allow(dead_code)] |
9 | | -use core::{ |
10 | | - mem::MaybeUninit, |
11 | | - ptr, |
12 | | - sync::atomic::{AtomicUsize, Ordering::Relaxed}, |
13 | | -}; |
14 | | - |
15 | | -// This structure represents a lazily initialized static usize value. Useful |
16 | | -// when it is preferable to just rerun initialization instead of locking. |
17 | | -// Both unsync_init and sync_init will invoke an init() function until it |
18 | | -// succeeds, then return the cached value for future calls. |
19 | | -// |
20 | | -// Both methods support init() "failing". If the init() method returns UNINIT, |
21 | | -// that value will be returned as normal, but will not be cached. |
22 | | -// |
23 | | -// Users should only depend on the _value_ returned by init() functions. |
24 | | -// Specifically, for the following init() function: |
25 | | -// fn init() -> usize { |
26 | | -// a(); |
27 | | -// let v = b(); |
28 | | -// c(); |
29 | | -// v |
30 | | -// } |
31 | | -// the effects of c() or writes to shared memory will not necessarily be |
32 | | -// observed and additional synchronization methods with be needed. |
33 | | -pub struct LazyUsize(AtomicUsize); |
34 | | - |
35 | | -impl LazyUsize { |
36 | | - pub const fn new() -> Self { |
37 | | - Self(AtomicUsize::new(Self::UNINIT)) |
38 | | - } |
39 | | - |
40 | | - // The initialization is not completed. |
41 | | - pub const UNINIT: usize = usize::max_value(); |
42 | | - |
43 | | - // Runs the init() function at least once, returning the value of some run |
44 | | - // of init(). Multiple callers can run their init() functions in parallel. |
45 | | - // init() should always return the same value, if it succeeds. |
46 | | - pub fn unsync_init(&self, init: impl FnOnce() -> usize) -> usize { |
47 | | - // Relaxed ordering is fine, as we only have a single atomic variable. |
48 | | - let mut val = self.0.load(Relaxed); |
49 | | - if val == Self::UNINIT { |
50 | | - val = init(); |
51 | | - self.0.store(val, Relaxed); |
52 | | - } |
53 | | - val |
54 | | - } |
55 | | -} |
56 | | - |
57 | | -// Identical to LazyUsize except with bool instead of usize. |
58 | | -pub struct LazyBool(LazyUsize); |
59 | | - |
60 | | -impl LazyBool { |
61 | | - pub const fn new() -> Self { |
62 | | - Self(LazyUsize::new()) |
63 | | - } |
64 | | - |
65 | | - pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool { |
66 | | - self.0.unsync_init(|| init() as usize) != 0 |
67 | | - } |
68 | | -} |
| 9 | +use core::{mem::MaybeUninit, ptr}; |
69 | 10 |
|
70 | 11 | /// Polyfill for `maybe_uninit_slice` feature's |
71 | 12 | /// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have |
|
0 commit comments