1d0a2ff35Sopenharmony_ci// Copyright 2016 lazy-static.rs Developers
2d0a2ff35Sopenharmony_ci//
3d0a2ff35Sopenharmony_ci// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4d0a2ff35Sopenharmony_ci// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5d0a2ff35Sopenharmony_ci// http://opensource.org/licenses/MIT>, at your option. This file may not be
6d0a2ff35Sopenharmony_ci// copied, modified, or distributed except according to those terms.
7d0a2ff35Sopenharmony_ci
8d0a2ff35Sopenharmony_ciextern crate core;
9d0a2ff35Sopenharmony_ciextern crate std;
10d0a2ff35Sopenharmony_ci
11d0a2ff35Sopenharmony_ciuse self::std::prelude::v1::*;
12d0a2ff35Sopenharmony_ciuse self::std::cell::Cell;
13d0a2ff35Sopenharmony_ciuse self::std::hint::unreachable_unchecked;
14d0a2ff35Sopenharmony_ciuse self::std::sync::Once;
15d0a2ff35Sopenharmony_ci#[allow(deprecated)]
16d0a2ff35Sopenharmony_cipub use self::std::sync::ONCE_INIT;
17d0a2ff35Sopenharmony_ci
18d0a2ff35Sopenharmony_ci// FIXME: Replace Option<T> with MaybeUninit<T> (stable since 1.36.0)
19d0a2ff35Sopenharmony_cipub struct Lazy<T: Sync>(Cell<Option<T>>, Once);
20d0a2ff35Sopenharmony_ci
21d0a2ff35Sopenharmony_ciimpl<T: Sync> Lazy<T> {
22d0a2ff35Sopenharmony_ci    #[allow(deprecated)]
23d0a2ff35Sopenharmony_ci    pub const INIT: Self = Lazy(Cell::new(None), ONCE_INIT);
24d0a2ff35Sopenharmony_ci
25d0a2ff35Sopenharmony_ci    #[inline(always)]
26d0a2ff35Sopenharmony_ci    pub fn get<F>(&'static self, f: F) -> &T
27d0a2ff35Sopenharmony_ci    where
28d0a2ff35Sopenharmony_ci        F: FnOnce() -> T,
29d0a2ff35Sopenharmony_ci    {
30d0a2ff35Sopenharmony_ci        self.1.call_once(|| {
31d0a2ff35Sopenharmony_ci            self.0.set(Some(f()));
32d0a2ff35Sopenharmony_ci        });
33d0a2ff35Sopenharmony_ci
34d0a2ff35Sopenharmony_ci        // `self.0` is guaranteed to be `Some` by this point
35d0a2ff35Sopenharmony_ci        // The `Once` will catch and propagate panics
36d0a2ff35Sopenharmony_ci        unsafe {
37d0a2ff35Sopenharmony_ci            match *self.0.as_ptr() {
38d0a2ff35Sopenharmony_ci                Some(ref x) => x,
39d0a2ff35Sopenharmony_ci                None => {
40d0a2ff35Sopenharmony_ci                    debug_assert!(false, "attempted to derefence an uninitialized lazy static. This is a bug");
41d0a2ff35Sopenharmony_ci
42d0a2ff35Sopenharmony_ci                    unreachable_unchecked()
43d0a2ff35Sopenharmony_ci                },
44d0a2ff35Sopenharmony_ci            }
45d0a2ff35Sopenharmony_ci        }
46d0a2ff35Sopenharmony_ci    }
47d0a2ff35Sopenharmony_ci}
48d0a2ff35Sopenharmony_ci
49d0a2ff35Sopenharmony_ciunsafe impl<T: Sync> Sync for Lazy<T> {}
50d0a2ff35Sopenharmony_ci
51d0a2ff35Sopenharmony_ci#[macro_export]
52d0a2ff35Sopenharmony_ci#[doc(hidden)]
53d0a2ff35Sopenharmony_cimacro_rules! __lazy_static_create {
54d0a2ff35Sopenharmony_ci    ($NAME:ident, $T:ty) => {
55d0a2ff35Sopenharmony_ci        static $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy::INIT;
56d0a2ff35Sopenharmony_ci    };
57d0a2ff35Sopenharmony_ci}
58