summaryrefslogtreecommitdiffstats
path: root/vendor/regex-automata/src/util/lazy.rs
blob: d8cac6ef44d3f17655956b6c0d721b1bd30d1a1a (plain)
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
use core::{
    cell::Cell,
    ptr,
    sync::atomic::{AtomicPtr, Ordering},
};

use alloc::{boxed::Box, vec::Vec};

#[inline(always)]
pub(crate) fn get_or_init<T: Send + Sync + 'static>(
    location: &'static AtomicPtr<T>,
    init: impl FnOnce() -> T,
) -> &'static T {
    let mut ptr = location.load(Ordering::Acquire);
    if ptr.is_null() {
        let new_dfa = Box::new(init());
        ptr = Box::into_raw(new_dfa);
        let result = location.compare_exchange(
            ptr::null_mut(),
            ptr,
            Ordering::AcqRel,
            Ordering::Acquire,
        );
        if let Err(old) = result {
            let redundant = unsafe { Box::from_raw(ptr) };
            drop(redundant);
            ptr = old;
        }
    }
    unsafe { &*ptr }
}