static_init/
lazy.rs

1use crate::phase_locker::{
2    SyncPhaseGuard, SyncPhaseLocker, SyncReadPhaseGuard, UnSyncPhaseGuard, UnSyncPhaseLocker,
3    UnSyncReadPhaseGuard,
4};
5use crate::{
6    generic_lazy::{
7        self, AccessError, DropedUnInited, GenericLazy, GenericLockedLazy, LazyData, LazyPolicy,
8        Primed, UnInited,
9    },
10    lazy_sequentializer::UnSyncSequentializer,
11    Finaly, Generator, GeneratorTolerance, Phase, Phased, StaticInfo, Uninit,
12};
13
14#[cfg(feature = "thread_local")]
15use crate::exit_sequentializer::ThreadExitSequentializer;
16
17use crate::{exit_sequentializer::ExitSequentializer, lazy_sequentializer::SyncSequentializer};
18
19use core::cell::Cell;
20use core::marker::PhantomData;
21use core::ops::{Deref, DerefMut};
22
23struct InitializedChecker<T>(PhantomData<T>);
24
25impl<Tol: GeneratorTolerance> LazyPolicy for InitializedChecker<Tol> {
26    #[inline(always)]
27    fn shall_init(p: Phase) -> bool {
28        if Tol::INIT_FAILURE {
29            !p.intersects(Phase::INITIALIZED)
30        } else {
31            p.is_empty()
32        }
33    }
34    #[inline(always)]
35    fn is_accessible(p: Phase) -> bool {
36        p.intersects(Phase::INITIALIZED)
37    }
38    #[inline(always)]
39    fn post_init_is_accessible(p: Phase) -> bool {
40        if Tol::INIT_FAILURE {
41            Self::initialized_is_accessible(p)
42        } else {
43            Self::is_accessible(p)
44        }
45    }
46    #[inline(always)]
47    fn initialized_is_accessible(_: Phase) -> bool {
48        true
49    }
50}
51
52struct InitializedSoftFinalizedCheckerGeneric<T, const REG_ALWAYS: bool>(PhantomData<T>);
53
54impl<Tol: GeneratorTolerance, const REG_ALWAYS: bool> LazyPolicy
55    for InitializedSoftFinalizedCheckerGeneric<Tol, REG_ALWAYS>
56{
57    #[inline(always)]
58    fn shall_init(p: Phase) -> bool {
59        if Tol::INIT_FAILURE {
60            !p.intersects(Phase::INITIALIZED)
61        } else {
62            p.is_empty()
63        }
64    }
65    #[inline(always)]
66    fn is_accessible(p: Phase) -> bool {
67        p.intersects(Phase::INITIALIZED)
68    }
69    #[inline(always)]
70    fn post_init_is_accessible(p: Phase) -> bool {
71        if Tol::INIT_FAILURE && (REG_ALWAYS || Tol::FINAL_REGISTRATION_FAILURE) {
72            debug_assert!(!REG_ALWAYS || p.intersects(Phase::REGISTERED));
73            Self::initialized_is_accessible(p)
74        } else {
75            Self::is_accessible(p)
76        }
77    }
78    #[inline(always)]
79    fn initialized_is_accessible(_: Phase) -> bool {
80        true
81    }
82}
83
84struct InitializedHardFinalizedCheckerGeneric<T, const REG_ALWAYS: bool>(PhantomData<T>);
85
86impl<Tol: GeneratorTolerance, const REG_ALWAYS: bool> LazyPolicy
87    for InitializedHardFinalizedCheckerGeneric<Tol, REG_ALWAYS>
88{
89    #[inline(always)]
90    fn shall_init(p: Phase) -> bool {
91        if Tol::INIT_FAILURE {
92            !p.intersects(Phase::INITIALIZED)
93        } else {
94            p.is_empty()
95        }
96    }
97    #[inline(always)]
98    fn is_accessible(p: Phase) -> bool {
99        p.intersects(Phase::INITIALIZED) && Self::initialized_is_accessible(p)
100    }
101    #[inline(always)]
102    fn post_init_is_accessible(p: Phase) -> bool {
103        if Tol::INIT_FAILURE && (REG_ALWAYS || Tol::FINAL_REGISTRATION_FAILURE) {
104            debug_assert!(!REG_ALWAYS || p.intersects(Phase::REGISTERED));
105            Self::initialized_is_accessible(p)
106        } else {
107            Self::is_accessible(p)
108        }
109    }
110    #[inline(always)]
111    fn initialized_is_accessible(p: Phase) -> bool {
112        !p.intersects(Phase::FINALIZED | Phase::FINALIZATION_PANICKED)
113    }
114}
115
116type InitializedSoftFinalizedChecker<T> = InitializedSoftFinalizedCheckerGeneric<T, false>;
117
118type InitializedHardFinalizedChecker<T> = InitializedHardFinalizedCheckerGeneric<T, false>;
119
120//Lesser lazy are initializer before main so registration will always succeed
121type InitializedSoftFinalizedCheckerLesser<T> = InitializedSoftFinalizedCheckerGeneric<T, true>;
122
123type InitializedHardFinalizedCheckerLesser<T> = InitializedHardFinalizedCheckerGeneric<T, true>;
124
125/// Thread local final registration always succeed for thread local on glibc plateforms
126#[cfg(all(feature = "thread_local", cxa_thread_at_exit))]
127type InitializedSoftFinalizedTLChecker<T> = InitializedSoftFinalizedCheckerGeneric<T, true>;
128
129#[cfg(all(feature = "thread_local", cxa_thread_at_exit))]
130type InitializedHardFinalizedTLChecker<T> = InitializedHardFinalizedCheckerGeneric<T, true>;
131
132#[cfg(all(feature = "thread_local", not(cxa_thread_at_exit)))]
133type InitializedSoftFinalizedTLChecker<T> = InitializedSoftFinalizedCheckerGeneric<T, false>;
134
135#[cfg(all(feature = "thread_local", not(cxa_thread_at_exit)))]
136type InitializedHardFinalizedTLChecker<T> = InitializedHardFinalizedCheckerGeneric<T, false>;
137
138/// Helper trait to ease access static lazy associated functions
139pub trait LazyAccess: Sized {
140    type Target;
141    /// Initialize if necessary then return a reference to the target.
142    ///
143    /// # Panics
144    ///
145    /// Panic if previous attempt to initialize has panicked and the lazy policy does not
146    /// tolorate further initialization attempt or if initialization
147    /// panic.
148    fn get(this: Self) -> Self::Target;
149    /// Return a reference to the target if initialized otherwise return an error.
150    fn try_get(this: Self) -> Result<Self::Target, AccessError>;
151    /// The current phase of the static
152    fn phase(this: Self) -> Phase;
153    /// Initialize the static if there were no previous attempt to initialize it.
154    fn init(this: Self) -> Phase;
155}
156
157macro_rules! impl_lazy {
158    ($tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:path, $locker:ty $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
159        impl_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker $(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?}
160        impl_lazy! {@deref $tp,$data$(,T:$tr)?$(,G:$trg)?}
161    };
162    (global $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker:ty $(,T: $tr: ident)?$(,G: $trg:ident)?,$doc:literal $(cfg($attr:meta))?) => {
163        impl_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe,'static}
164        impl_lazy! {@deref_global $tp,$data$(,T:$tr)?$(,G:$trg)?}
165    };
166    (static $tp:ident, $man:ident$(<$x:ident>)?, $checker: ident, $data:ty, $locker:ty $(,T: $tr: ident)?$(,G: $trg:ident)?,$doc:literal $(cfg($attr:meta))?) => {
167        impl_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe,'static}
168        impl_lazy! {@deref_static $tp,$data$(,T:$tr)?$(,G:$trg)?}
169    };
170    (thread_local_static $tp:ident, $man:ident$(<$x:ident>)?, $checker: ident, $data:ty, $locker:ty $(,T: $tr: ident)?$(,G: $trg:ident)?,$doc:literal $(cfg($attr:meta))?) => {
171        impl_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe,'static}
172        impl_lazy! {@deref_thread_local $tp,$data$(,T:$tr)?$(,G:$trg)?}
173    };
174    (@deref $tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
175        impl<T, G> $tp<T, G>
176        where G: Generator<T>,
177        $(G:$trg, T:Sync,)?
178        $(T:$tr,)?
179        {
180            #[inline(always)]
181            /// Initialize if necessary then return a reference to the target.
182            ///
183            /// # Panics
184            ///
185            /// Panic if previous attempt to initialize has panicked and the lazy policy does not
186            /// tolorate further initialization attempt or if initialization
187            /// panic.
188            pub fn get(this: &Self) -> &T {
189                this.__private.init_then_get()
190            }
191            #[inline(always)]
192            /// Return a reference to the target if initialized otherwise return an error.
193            pub fn try_get(this: &Self) -> Result<&'_ T,AccessError> {
194                this.__private.try_get()
195            }
196            #[inline(always)]
197            /// Initialize and return a mutable reference to the target
198            ///
199            /// This method is extremly efficient as it does not requires any
200            /// form of locking when initializing
201            pub fn get_mut(this: &mut Self) -> &mut T {
202                this.__private.only_init_then_get_mut()
203            }
204            #[inline(always)]
205            /// Return a mutable reference to the target if initialized otherwise return an error.
206            ///
207            /// This method is extremly efficient as it does not requires any
208            /// form of locking when initializing
209            pub fn try_get_mut(this: &mut Self) -> Result<&'_ mut T,AccessError> {
210                this.__private.try_get_mut()
211            }
212            #[inline(always)]
213            /// Return the phase
214            pub fn phase(this: & Self) -> Phase {
215                Phased::phase(&this.__private)
216            }
217            #[inline(always)]
218            /// Initialize the lazy if not yet initialized
219            ///
220            /// # Panic
221            ///
222            /// Panic if the generator panics
223            pub fn init(this: & Self) -> Phase {
224                GenericLazy::init(&this.__private)
225            }
226        }
227        impl<T, G> Deref for $tp<T, G>
228        where G: Generator<T>,
229        $(G:$trg, T:Sync,)?
230        $(T:$tr,)?
231        {
232            type Target = T;
233            #[inline(always)]
234            fn deref(&self) -> &Self::Target {
235                Self::get(self)
236            }
237        }
238
239        impl<T, G> DerefMut for $tp<T, G>
240        where G: Generator<T>,
241        $(G:$trg, T:Sync,)?
242        $(T:$tr,)?
243        {
244            #[inline(always)]
245            fn deref_mut(&mut self) -> &mut Self::Target {
246                Self::get_mut(self)
247            }
248        }
249
250        impl<'a,T,G> LazyAccess for &'a $tp<T,G>
251            where G: Generator<T>,
252            $(G:$trg, T:Sync,)?
253            $(T:$tr,)?
254            {
255            type Target = &'a T;
256             #[inline(always)]
257             fn get(this: Self) -> &'a T {
258                 $tp::get(this)
259             }
260             #[inline(always)]
261             fn try_get(this: Self) -> Result<&'a T,AccessError>{
262                 $tp::try_get(this)
263             }
264             #[inline(always)]
265             fn phase(this: Self) -> Phase{
266                 $tp::phase(this)
267             }
268             #[inline(always)]
269             fn init(this: Self) -> Phase {
270                 $tp::init(this)
271             }
272        }
273
274    };
275    (@deref_static $tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
276        impl<T, G> $tp<T, G>
277        where G: 'static + Generator<T>,
278        $(G:$trg, T:Sync,)?
279        $(T:$tr,)?
280        {
281            #[inline(always)]
282            /// Initialize if necessary then return a reference to the target.
283            ///
284            /// # Panics
285            ///
286            /// Panic if previous attempt to initialize has panicked and the lazy policy does not
287            /// tolorate further initialization attempt or if initialization
288            /// panic.
289            pub fn get(this: &'static Self) -> &'static T {
290                 // SAFETY The object is required to have 'static lifetime by construction
291                 this.__private.init_then_get()
292            }
293            #[inline(always)]
294            /// Return a reference to the target if initialized otherwise return an error.
295            pub fn try_get(this: &'static Self) -> Result<&'static T,AccessError> {
296                 // SAFETY The object is required to have 'static lifetime by construction
297                 this.__private.try_get()
298            }
299            #[inline(always)]
300            /// Return the phase
301            pub fn phase(this: &'static Self) -> Phase {
302                Phased::phase(&this.__private)
303            }
304            #[inline(always)]
305            /// Initialize the lazy if not yet initialized
306            ///
307            /// # Panic
308            ///
309            /// Panic if the generator panics
310            pub fn init(this: &'static Self) -> Phase {
311                GenericLazy::init(&this.__private)
312            }
313        }
314        impl<T, G> Deref for $tp<T, G>
315        where G: 'static + Generator<T>,
316        T:'static,
317        $(G:$trg, T:Sync,)?
318        $(T:$tr,)?
319        {
320            type Target = T;
321            #[inline(always)]
322            fn deref(&self) -> &Self::Target {
323                 // SAFETY The object is required to have 'static lifetime by construction
324                 Self::get(unsafe{as_static(self)})
325            }
326        }
327
328        impl<T,G> LazyAccess for &'static $tp<T,G>
329            where G: 'static + Generator<T>,
330            $(G:$trg, T:Sync,)?
331            $(T:$tr,)?
332            {
333            type Target = &'static T;
334             #[inline(always)]
335             fn get(this: Self) -> &'static T {
336                 $tp::get(this)
337             }
338             #[inline(always)]
339             fn try_get(this: Self) -> Result<&'static T,AccessError>{
340                 $tp::try_get(this)
341             }
342             #[inline(always)]
343             fn phase(this: Self) -> Phase{
344                 $tp::phase(this)
345             }
346             #[inline(always)]
347             fn init(this: Self) -> Phase {
348                 $tp::init(this)
349             }
350        }
351
352    };
353    (@deref_global $tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
354        impl<T, G> $tp<T, G>
355        where G: 'static + Generator<T>,
356        $(G:$trg, T:Sync,)?
357        $(T:$tr,)?
358        {
359            #[inline(always)]
360            /// Return a reference to the target if initialized otherwise return an error.
361            pub fn try_get(this: &'static Self) -> Result<&'static T, AccessError> {
362                if inited::global_inited_hint() {
363                    // SAFETY The object is initialized a program start-up as long
364                    // as it is constructed through the macros #[dynamic(quasi_lazy)]
365                    // If initialization failed, the program terminates before the
366                    // global_inited_hint is set. So if the global_initied_hint is
367                    // set all LesserLazy are guaranteed to be initialized
368                    // Moreover global lazy are never dropped
369                    // TODO: get_unchecked
370                    Ok(unsafe{this.__private.get_unchecked()})
371                } else {
372                    this.__private.try_get()
373                }
374            }
375            #[inline(always)]
376            /// Initialize if necessary then return a reference to the target.
377            ///
378            /// # Panics
379            ///
380            /// Panic if previous attempt to initialize has panicked and the lazy policy does not
381            /// tolorate further initialization attempt or if initialization
382            /// panic.
383            pub fn get(this: &'static Self) -> &'static T {
384                if inited::global_inited_hint() {
385                    // SAFETY The object is initialized a program start-up as long
386                    // as it is constructed through the macros #[dynamic(quasi_lazy)]
387                    // If initialization failed, the program terminates before the
388                    // global_inited_hint is set. So if the global_initied_hint is
389                    // set all LesserLazy are guaranteed to be initialized
390                    // Moreover global lazy are never dropped
391                    unsafe{this.__private.get_unchecked()}
392                } else {
393                    this.__private.init_then_get()
394                }
395            }
396            #[inline(always)]
397            /// Return the phase
398            pub fn phase(this: &'static Self) -> Phase {
399                Phased::phase(&this.__private)
400            }
401            #[inline(always)]
402            /// Initialize the lazy if not yet initialized
403            ///
404            /// # Panic
405            ///
406            /// Panic if the generator panics
407            pub fn init(this: &'static Self) -> Phase {
408                GenericLazy::init(&this.__private)
409            }
410        }
411        impl<T, G> Deref for $tp<T, G>
412        where G: 'static + Generator<T>,
413        T:'static,
414        $(G:$trg, T:Sync,)?
415        $(T:$tr,)?
416        {
417            type Target = T;
418            #[inline(always)]
419            fn deref(&self) -> &Self::Target {
420                // SAFETY The object is initialized a program start-up as long
421                // as it is constructed through the macros #[dynamic(quasi_lazy)]
422                // If initialization failed, the program terminates before the
423                // global_inited_hint is set. So if the global_initied_hint is
424                // set all LesserLazy are guaranteed to be initialized
425                Self::get(unsafe{as_static(self)})
426            }
427        }
428        impl<T,G> LazyAccess for &'static $tp<T,G>
429            where G: 'static + Generator<T>,
430            $(G:$trg, T:Sync,)?
431            $(T:$tr,)?
432            {
433            type Target = &'static T;
434             #[inline(always)]
435             fn get(this: Self) -> &'static T {
436                 $tp::get(this)
437             }
438             #[inline(always)]
439             fn try_get(this: Self) -> Result<&'static T,AccessError>{
440                 $tp::try_get(this)
441             }
442             #[inline(always)]
443             fn phase(this: Self) -> Phase{
444                 $tp::phase(this)
445             }
446             #[inline(always)]
447             fn init(this: Self) -> Phase{
448                 $tp::init(this)
449             }
450        }
451
452    };
453    (@deref_thread_local $tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
454        impl<T, G> $tp<T, G>
455        //where $data: 'static + LazyData<Target=T>,
456        where G: 'static + Generator<T>,
457        T:'static,
458        $(G:$trg, T:Sync,)?
459        $(T:$tr,)?
460        {
461            #[inline(always)]
462            /// Initialize if necessary then return a reference to the target.
463            ///
464            /// # Panics
465            ///
466            /// Panic if previous attempt to initialize has panicked and the lazy policy does not
467            /// tolorate further initialization attempt or if initialization
468            /// panic.
469            pub fn get(this: &Self) -> &T {
470                 // SAFETY The object is required to have 'static lifetime by construction
471                 unsafe {as_static(&this.__private).init_then_get()}
472            }
473            #[inline(always)]
474            /// Return a reference to the target if initialized otherwise return an error.
475            pub fn try_get(this: &Self) -> Result<&T,AccessError> {
476                 // SAFETY The object is required to have 'static lifetime by construction
477                 unsafe{as_static(&this.__private).try_get()}
478            }
479            #[inline(always)]
480            /// Return the phase
481            pub fn phase(this: &Self) -> Phase {
482                Phased::phase(unsafe{as_static(&this.__private)})
483            }
484            #[inline(always)]
485            /// Initialize the lazy if not yet initialized
486            ///
487            /// # Panic
488            ///
489            /// Panic if the generator panics
490            pub fn init(this: &Self) -> Phase {
491                GenericLazy::init(unsafe{as_static(&this.__private)})
492            }
493        }
494
495        impl<T, G> Deref for $tp<T, G>
496        where G: 'static + Generator<T>,
497        T:'static,
498        $(G:$trg, T:Sync,)?
499        $(T:$tr,)?
500        {
501            type Target = T;
502            #[inline(always)]
503            fn deref(&self) -> &Self::Target {
504                 Self::get(self)
505            }
506        }
507
508        impl<'a,T,G> LazyAccess for &'a $tp<T,G>
509            where G: 'static + Generator<T>,
510            T:'static,
511            $(G:$trg, T:Sync,)?
512            $(T:$tr,)?
513            {
514            type Target = &'a T;
515             #[inline(always)]
516             fn get(this: Self) -> &'a T {
517                 $tp::get(this)
518             }
519             #[inline(always)]
520             fn try_get(this: Self) -> Result<&'a T,AccessError>{
521                 $tp::try_get(this)
522             }
523             #[inline(always)]
524             fn phase(this: Self) -> Phase{
525                 $tp::phase(this)
526             }
527             #[inline(always)]
528             fn init(this: Self) -> Phase {
529                 $tp::init(this)
530             }
531        }
532
533    };
534    (@proc $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty,$locker:ty $(,T: $tr: ident)?$(,G: $trg:ident)?,$doc:literal $(cfg($attr:meta))? $(,$safe:ident)?$(,$static:lifetime)?) => {
535        #[doc=$doc]
536        $(#[cfg_attr(docsrs,doc(cfg($attr)))])?
537        pub struct $tp<T, G = fn() -> T> {
538            __private: GenericLazy<$data, G, $man$(::<$x>)?, $checker::<G>>,
539        }
540        impl<T, G> Phased for $tp<T, G>
541        //where $data: $($static +)? LazyData<Target=T>,
542        where G: $($static +)? Generator<T>,
543        $(G:$trg, T:Sync,)?
544        $(T:$tr,)?
545        {
546            fn phase(this: &Self) -> Phase {
547                Phased::phase(&this.__private)
548            }
549        }
550
551        impl<T, G> $tp<T, G> {
552            #[inline(always)]
553            /// Build a new static object
554            ///
555            /// # Safety
556            ///
557            /// This function may be unsafe if building any thing else than a thread local object
558            /// or a static will be the cause of undefined behavior
559            pub const $($safe)? fn from_generator(f: G) -> Self {
560                #[allow(unused_unsafe)]
561                Self {
562
563                    __private: unsafe{GenericLazy::new(f, $man::new(<$locker>::new(Phase::empty())),<$data>::INIT)},
564                }
565            }
566            #[inline(always)]
567            /// Build a new static object with debug information
568            ///
569            /// # Safety
570            ///
571            /// This function may be unsafe if building any thing else than a thread local object
572            /// or a static will be the cause of undefined behavior
573            pub const $($safe)?  fn from_generator_with_info(f: G, info: StaticInfo) -> Self {
574                #[allow(unused_unsafe)]
575                Self {
576                    __private: unsafe{GenericLazy::new_with_info(f, $man::new(<$locker>::new(Phase::empty())), <$data>::INIT,info)},
577                }
578            }
579        }
580
581    };
582}
583
584impl_lazy! {Lazy,SyncSequentializer<G>,InitializedChecker,UnInited::<T>,SyncPhaseLocker,
585"A type that initialize itself only once on the first access"}
586
587impl_lazy! {global LesserLazy,SyncSequentializer<G>,InitializedChecker,UnInited::<T>,SyncPhaseLocker,
588"The actual type of statics attributed with [#[dynamic]](macro@crate::dynamic). \
589\
590The method [from_generator](Self::from_generator) is unsafe because this kind of static \
591can only safely be used through this attribute macros."
592}
593
594impl_lazy! {static LazyFinalize,ExitSequentializer<G>,InitializedSoftFinalizedChecker,UnInited::<T>,SyncPhaseLocker,T:Finaly,G:Sync,
595"The actual type of statics attributed with [#[dynamic(lazy,finalize)]](macro@crate::dynamic) \
596\
597The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable static."
598}
599
600impl_lazy! {global LesserLazyFinalize,ExitSequentializer<G>,InitializedSoftFinalizedCheckerLesser,UnInited::<T>,SyncPhaseLocker,T:Finaly,G:Sync,
601"The actual type of statics attributed with [#[dynamic(finalize)]](macro@crate::dynamic). \
602\
603The method [from_generator](Self::from_generator) is unsafe because this kind of static \
604can only safely be used through this attribute macros."
605}
606
607impl_lazy! {UnSyncLazy,UnSyncSequentializer<G>,InitializedChecker,UnInited::<T>,UnSyncPhaseLocker,
608"A version of [Lazy] whose reference can not be passed to other thread"
609}
610
611#[cfg(feature = "thread_local")]
612impl_lazy! {thread_local_static UnSyncLazyFinalize,ThreadExitSequentializer<G>,InitializedSoftFinalizedTLChecker,UnInited::<T>,UnSyncPhaseLocker,T:Finaly,
613"The actual type of thread_local statics attributed with [#[dynamic(finalize)]](macro@crate::dynamic) \
614\
615The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable static." cfg(feature="thread_local")
616}
617#[cfg(feature = "thread_local")]
618impl_lazy! {thread_local_static UnSyncLazyDroped,ThreadExitSequentializer<G>,InitializedHardFinalizedTLChecker,DropedUnInited::<T>,UnSyncPhaseLocker,
619"The actual type of thread_local statics attributed with [#[dynamic(drop)]](macro@crate::dynamic) \
620\
621The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable static." cfg(feature="thread_local")
622}
623
624use core::fmt::{self, Debug, Formatter};
625macro_rules! non_static_debug {
626    ($tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
627        impl<T:Debug, G> Debug for $tp<T, G>
628            //where $data: LazyData<Target=T>,
629            where G: Generator<T>,
630            $(G:$trg, T:Sync,)?
631            $(T:$tr,)?
632        {
633            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
634                if ($tp::phase(self) & Phase::INITIALIZED).is_empty() {
635                    write!(f,"UnInitialized")
636                } else {
637                    write!(f,"{:?}",**self)
638                }
639            }
640        }
641    }
642}
643macro_rules! non_static_impls {
644    ($tp:ident, $data:ty $(,T: $tr:ident)? $(,G: $trg:ident)?) => {
645        impl<T, G> $tp<T, Cell<Option<G>>>
646        where
647            G: FnOnce() -> T,
648        {
649            #[inline(always)]
650            pub fn new(g: G) -> Self {
651                Self::from_generator(Cell::new(Some(g)))
652            }
653        }
654        impl<T: Default> Default for $tp<T, fn() -> T> {
655            #[inline(always)]
656            fn default() -> Self {
657                Self::from_generator(T::default)
658            }
659        }
660    };
661}
662non_static_impls! {Lazy,UnInited::<T>}
663non_static_debug! {Lazy,UnInited::<T>}
664non_static_impls! {UnSyncLazy,UnInited::<T>}
665non_static_debug! {UnSyncLazy,UnInited::<T>}
666
667impl<T, G> Drop for Lazy<T, G> {
668    #[inline(always)]
669    fn drop(&mut self) {
670        if Phased::phase(GenericLazy::sequentializer(&self.__private))
671            .intersects(Phase::INITIALIZED)
672        {
673            unsafe {
674                GenericLazy::get_raw_data(&self.__private)
675                    .get()
676                    .drop_in_place()
677            }
678        }
679    }
680}
681impl<T, G> Drop for UnSyncLazy<T, G> {
682    #[inline(always)]
683    fn drop(&mut self) {
684        if Phased::phase(GenericLazy::sequentializer(&self.__private))
685            .intersects(Phase::INITIALIZED)
686        {
687            unsafe {
688                GenericLazy::get_raw_data(&self.__private)
689                    .get()
690                    .drop_in_place()
691            }
692        }
693    }
694}
695
696macro_rules! non_static_mut_debug {
697    ($tp:ident, $data:ty $(,T: $tr: ident)?$(,G: $trg:ident)?) => {
698        impl<T:Debug, G> Debug for $tp<T, G>
699            where G: Generator<T>,
700            $(G:$trg, T:Sync,)?
701            $(T:$tr,)?
702        {
703            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
704                if ($tp::phase(self) & Phase::INITIALIZED).is_empty() {
705                    write!(f,"UnInitialized")
706                } else {
707                    write!(f,"{:?}",*self.read())
708                }
709            }
710        }
711    }
712}
713
714macro_rules! extend_locked_lazy {
715    () => {
716        non_static_impls! {LockedLazy,UnInited::<T>}
717        non_static_mut_debug! {LockedLazy,UnInited::<T>}
718        impl<T: Send, G: Generator<T>> LockedLazy<T, G> {
719            #[inline(always)]
720            /// Initialize and return a mutable reference to the target
721            ///
722            /// This method is extremly efficient as it does not requires any
723            /// form of locking when initializing
724            pub fn get_mut(&mut self) -> &mut T {
725                self.__private.only_init_then_get_mut()
726            }
727            #[inline(always)]
728            /// Return a mutable reference to the target if initialized otherwise return an error.
729            ///
730            /// This method is extremly efficient as it does not requires any
731            /// form of locking when initializing
732            pub fn try_get_mut(&mut self) -> Result<&mut T, AccessError> {
733                self.__private.try_get_mut()
734            }
735        }
736        impl<T, G> Drop for LockedLazy<T, G> {
737            #[inline(always)]
738            fn drop(&mut self) {
739                if Phased::phase(GenericLockedLazy::sequentializer(&self.__private))
740                    .intersects(Phase::INITIALIZED)
741                {
742                    unsafe { (&*self.__private).get().drop_in_place() }
743                }
744            }
745        }
746    };
747}
748macro_rules! extend_unsync_locked_lazy {
749    () => {
750        non_static_impls! {UnSyncLockedLazy,UnInited::<T>}
751        non_static_mut_debug! {UnSyncLockedLazy,UnInited::<T>}
752
753        impl<T, G: Generator<T>> UnSyncLockedLazy<T, G> {
754            #[inline(always)]
755            /// Initialize and return a mutable reference to the target
756            ///
757            /// This method is extremly efficient as it does not requires any
758            /// form of locking when initializing
759            pub fn get_mut(&mut self) -> &mut T {
760                self.__private.only_init_then_get_mut()
761            }
762            #[inline(always)]
763            /// Return a mutable reference to the target if initialized otherwise return an error.
764            ///
765            /// This method is extremly efficient as it does not requires any
766            /// form of locking when initializing
767            pub fn try_get_mut(&mut self) -> Result<&mut T, AccessError> {
768                self.__private.try_get_mut()
769            }
770        }
771
772        impl<T, G> Drop for UnSyncLockedLazy<T, G> {
773            #[inline(always)]
774            fn drop(&mut self) {
775                if Phased::phase(GenericLockedLazy::sequentializer(&self.__private))
776                    .intersects(Phase::INITIALIZED)
777                {
778                    unsafe { (&*self.__private).get().drop_in_place() }
779                }
780            }
781        }
782    };
783}
784
785macro_rules! impl_mut_lazy {
786    ($mod: ident $(:$extension:ident)?, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker:ty, $gdw: ident, $gd: ident $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
787        pub mod $mod {
788            use super::*;
789        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?}
790        impl_mut_lazy! {@lock $tp,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?}
791        impl_mut_lazy! {@uninited $tp, $man$(<$x>)?, $data, $locker}
792            $($extension!{})?
793        }
794        #[doc(inline)]
795        pub use $mod::$tp;
796    };
797    (static $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker: ty, $gdw: ident,$gd:ident  $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
798        pub mod $mod {
799            use super::*;
800        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, 'static}
801        impl_mut_lazy! {@lock $tp,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)? , 'static}
802        impl_mut_lazy! {@uninited $tp, $man$(<$x>)?, $data, $locker}
803        }
804        #[doc(inline)]
805        pub use $mod::$tp;
806    };
807    (const_static $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker: ty, $gdw: ident,$gd:ident  $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
808        pub mod $mod {
809            use super::*;
810        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, 'static}
811        impl_mut_lazy! {@const_lock $tp,$checker, $data,$gdw,$gd$(,T:$tr)?$(,G:$trg)? , 'static}
812        impl_mut_lazy! {@prime $tp, $man$(<$x>)?, $data, $locker}
813        }
814        #[doc(inline)]
815        pub use $mod::$tp;
816    };
817    (thread_local $mod: ident $(:$extension:ident)?, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty,$locker: ty,  $gdw: ident,$gd:ident  $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
818        pub mod $mod {
819            use super::*;
820        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe}
821        impl_mut_lazy! {@lock_thread_local $tp,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?}
822        impl_mut_lazy! {@uninited $tp, $man$(<$x>)?, $data, $locker, unsafe}
823            $($extension!{})?
824        }
825        #[doc(inline)]
826        pub use $mod::$tp;
827    };
828    (global $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty,$locker: ty,  $gdw: ident,$gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
829        pub mod $mod {
830            use super::*;
831        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe, 'static}
832        impl_mut_lazy! {@lock_global $tp,$checker,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?}
833        impl_mut_lazy! {@uninited $tp, $man$(<$x>)?, $data, $locker, unsafe}
834        }
835        #[doc(inline)]
836        pub use $mod::$tp;
837    };
838    (primed_static $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker:ty, $gdw: ident, $gd: ident $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
839        pub mod $mod {
840            use super::*;
841        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, 'static}
842        impl_mut_lazy! {@lock $tp,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?, 'static}
843        impl_mut_lazy! {@prime $tp, $man$(<$x>)?, $data, $locker}
844        impl_mut_lazy! {@prime_static $tp, $checker, $data, $gdw, $gd$(,T:$tr)?$(,G:$trg)?}
845        }
846        #[doc(inline)]
847        pub use $mod::$tp;
848    };
849    (global_primed_static $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker:ty, $gdw: ident, $gd: ident $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
850        pub mod $mod {
851            use super::*;
852        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, 'static}
853        impl_mut_lazy! {@lock_global $tp,$checker,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?}
854        impl_mut_lazy! {@prime $tp, $man$(<$x>)?, $data, $locker}
855        impl_mut_lazy! {@prime_global $tp, $checker, $data, $gdw, $gd$(,T:$tr)?$(,G:$trg)?}
856        }
857        #[doc(inline)]
858        pub use $mod::$tp;
859    };
860    (primed_thread_local $mod: ident, $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty,$locker: ty,  $gdw: ident,$gd:ident  $(,T: $tr: ident)?$(,G: $trg:ident)?, $doc:literal $(cfg($attr:meta))?) => {
861        pub mod $mod {
862            use super::*;
863        impl_mut_lazy! {@proc $tp,$man$(<$x>)?,$checker,$data,$locker,$gdw,$gd$(,T:$tr)?$(,G:$trg)?,$doc $(cfg($attr))?, unsafe}
864        impl_mut_lazy! {@lock_thread_local $tp,$data,$gdw,$gd$(,T:$tr)?$(,G:$trg)?}
865        impl_mut_lazy! {@prime $tp, $man$(<$x>)?, $data, $locker, unsafe}
866        impl_mut_lazy! {@prime_thread_local $tp, $checker, $data, $gdw, $gd$(,T:$tr)?$(,G:$trg)?}
867        }
868        #[doc(inline)]
869        pub use $mod::$tp;
870    };
871    (@lock $tp:ident, $data:ty, $gdw: ident, $gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)? $(,$static:lifetime)?) => {
872        impl<T, G> $tp<T, G>
873        //where $data: $($static+)? LazyData<Target=T>,
874        where G:$($static +)? Generator<T>,
875        $(T: $static,)?
876        $(G:$trg, T:Send,)?
877        $(T:$tr,)?
878        {
879            #[inline(always)]
880            /// Initialize if necessary and returns a read lock
881            ///
882            /// # Panic
883            ///
884            /// Panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
885            #[allow(elided_named_lifetimes)]
886            pub fn read(&$($static)? self) -> ReadGuard<'_,T> {
887               ReadGuard(GenericLockedLazy::init_then_read_lock(&self.__private))
888            }
889            #[inline(always)]
890            /// Initialize if necessary and returns some read lock if the lazy is not
891            /// already write locked. If the lazy is already write locked it returns `None`
892            ///
893            /// # Panic
894            ///
895            /// If locks succeeds, panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
896            #[allow(elided_named_lifetimes)]
897            pub fn fast_read(&$($static)? self) -> Option<ReadGuard<'_,T>> {
898               GenericLockedLazy::fast_init_then_read_lock(&self.__private).map(ReadGuard)
899            }
900            #[inline(always)]
901            /// Get a read lock if the lazy is initialized or an [AccessError]
902            #[allow(elided_named_lifetimes)]
903            pub fn try_read(&$($static)? self) -> Result<ReadGuard<'_,T>,AccessError> {
904               GenericLockedLazy::try_read_lock(&self.__private).map(ReadGuard)
905            }
906            #[inline(always)]
907            /// if the lazy is not already write locked: get a read lock if the lazy is initialized or an [AccessError].
908            /// Otherwise returns `None`
909            #[allow(elided_named_lifetimes)]
910            pub fn fast_try_read(&$($static)? self) -> Option<Result<ReadGuard<'_,T>,AccessError>> {
911               GenericLockedLazy::fast_try_read_lock(&self.__private).map(|r| r.map(ReadGuard))
912            }
913            #[inline(always)]
914            /// Initialize if necessary and returns a write lock
915            ///
916            /// # Panic
917            ///
918            /// Panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
919            #[allow(elided_named_lifetimes)]
920            pub fn write(&$($static)? self) -> WriteGuard<'_,T> {
921               WriteGuard(GenericLockedLazy::init_then_write_lock(&self.__private))
922            }
923            #[inline(always)]
924            /// Initialize if necessary and returns some write lock if the lazy is not
925            /// already write locked. If the lazy is already read or write locked it returns `None`
926            ///
927            /// # Panic
928            ///
929            /// If locks succeeds, panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
930            #[allow(elided_named_lifetimes)]
931            pub fn fast_write(&$($static)? self) -> Option<WriteGuard<'_,T>> {
932               GenericLockedLazy::fast_init_then_write_lock(&self.__private).map(WriteGuard)
933            }
934            #[inline(always)]
935            /// Get a read lock if the lazy is initialized or an [AccessError]
936            #[allow(elided_named_lifetimes)]
937            pub fn try_write(&$($static)? self) -> Result<WriteGuard<'_,T>,AccessError> {
938               GenericLockedLazy::try_write_lock(&self.__private).map(WriteGuard)
939            }
940            #[inline(always)]
941            /// if the lazy is not already read or write locked: get a write lock if the lazy is initialized or an [AccessError] . Otherwise returns `None`
942            #[allow(elided_named_lifetimes)]
943            pub fn fast_try_write(&$($static)? self) -> Option<Result<WriteGuard<'_,T>,AccessError>> {
944               GenericLockedLazy::fast_try_write_lock(&self.__private).map(|r| r.map(WriteGuard))
945            }
946            #[inline(always)]
947            /// Initialize the lazy if no previous attempt to initialized it where performed
948            pub fn init(&$($static)? self) {
949                let _ = GenericLockedLazy::init_then_write_lock(&self.__private);
950            }
951        }
952
953    };
954    (@const_lock $tp:ident, $checker: ident, $data:ty, $gdw: ident, $gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)? $(,$static:lifetime)?) => {
955        impl<T, G> $tp<T, G>
956        where G: $($static +)? Generator<T>,
957        T:Uninit,
958        $(T:$static ,)?
959        $(G:$trg, T:Send,)?
960        $(T:$tr,)?
961        {
962            #[inline(always)]
963            /// get read lock
964            ///
965            /// # Panic
966            ///
967            /// Panics if the lazy was droped
968            pub fn read(&'static self) -> ReadGuard<'_,T> {
969                    let l = unsafe{GenericLockedLazy::read_lock_unchecked(&self.__private)};
970                    assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(&l)));
971                    ReadGuard(l)
972            }
973            /// Returns some read lock if the lazy is not
974            /// already write locked. If the lazy is already write locked it returns `None`
975            ///
976            /// # Panic
977            ///
978            /// If locks succeeds, panics if the lazy was droped
979            #[inline(always)]
980            pub fn fast_read(&'static self) -> Option<ReadGuard<'_,T>> {
981                    let l = unsafe{GenericLockedLazy::fast_read_lock_unchecked(&self.__private)};
982                    if let Some(l) = &l {
983                        assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(l)));
984                    }
985                    l.map(ReadGuard)
986            }
987            #[inline(always)]
988            /// Return a read lock to the initialized value or an
989            /// error containing a read lock to the post uninited value
990            pub fn primed_read(&'static self) -> Result<ReadGuard<'_,T>,ReadGuard<'_,T>> {
991               let l = unsafe {GenericLockedLazy::read_lock_unchecked(&self.__private)};
992               let p = Phased::phase(&l);
993               if <$checker::<G>>::initialized_is_accessible(p) {
994                   Ok(ReadGuard(l))
995               } else {
996                   Err(ReadGuard(l))
997               }
998            }
999        }
1000
1001    };
1002    (@lock_thread_local $tp:ident, $data:ty,$gdw:ident,$gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?) => {
1003
1004        use super::as_static;
1005
1006        impl<T, G> $tp<T, G>
1007        //where $data: 'static + LazyData<Target=T>,
1008        where G: 'static + Generator<T>,
1009        T: 'static,
1010        $(G:$trg, T:Send,)?
1011        $(T:$tr,)?
1012        {
1013            #[inline(always)]
1014            /// Initialize if necessary and returns a read lock
1015            ///
1016            /// # Panic
1017            ///
1018            /// Panics if initialization panics or if initialization has panicked in a previous
1019            /// attempt to initialize.
1020            pub fn read(&self) -> ReadGuard<'_,T> {
1021                ReadGuard(GenericLockedLazy::init_then_read_lock(unsafe{as_static(&self.__private)}))
1022            }
1023            #[inline(always)]
1024            /// Initialize if necessary and returns some read lock if the lazy is not already write
1025            /// locked. If the lazy is already write locked it returns `None`
1026            ///
1027            /// # Panic
1028            ///
1029            /// If locks succeeds, panics if initialization panics or if initialization has
1030            /// panicked in a previous attempt to initialize.
1031            pub fn fast_read(&self) -> Option<ReadGuard<'_,T>> {
1032               GenericLockedLazy::fast_init_then_read_lock(unsafe{as_static(&self.__private)}).map(ReadGuard)
1033            }
1034            #[inline(always)]
1035            /// Get a read lock if the lazy is initialized or an [AccessError]
1036            pub fn try_read(&self) -> Result<ReadGuard<'_,T>,AccessError> {
1037               GenericLockedLazy::try_read_lock(unsafe{as_static(&self.__private)}).map(ReadGuard)
1038            }
1039            #[inline(always)]
1040            /// if the lazy is not already write locked: get a read lock if the lazy is initialized
1041            /// or an [AccessError]. Otherwise returns `None`
1042            pub fn fast_try_read(&self) -> Option<Result<ReadGuard<'_,T>,AccessError>> {
1043               GenericLockedLazy::fast_try_read_lock(unsafe{as_static(&self.__private)}).map(|r| r.map(ReadGuard))
1044            }
1045            #[inline(always)]
1046            /// Initialize if necessary and returns a write lock
1047            ///
1048            /// # Panic
1049            ///
1050            /// Panics if initialization panics or if initialization has panicked in a previous
1051            /// attempt to initialize.
1052            pub fn write(&self) -> WriteGuard<'_,T> {
1053                WriteGuard(GenericLockedLazy::init_then_write_lock(unsafe{as_static(&self.__private)}))
1054            }
1055            #[inline(always)]
1056            /// Initialize if necessary and returns some write lock if the lazy is not
1057            /// already write locked. If the lazy is already read or write locked it returns `None`
1058            ///
1059            /// # Panic
1060            ///
1061            /// If locks succeeds, panics if initialization panics or if initialization has
1062            /// panicked in a previous attempt to initialize.
1063            pub fn fast_write(&self) -> Option<WriteGuard<'_,T>> {
1064               GenericLockedLazy::fast_init_then_write_lock(unsafe{as_static(&self.__private)}).map(WriteGuard)
1065            }
1066            #[inline(always)]
1067            /// Get a read lock if the lazy is initialized or an [AccessError]
1068            pub fn try_write(&self) -> Result<WriteGuard<'_,T>,AccessError> {
1069               GenericLockedLazy::try_write_lock(unsafe{as_static(&self.__private)}).map(WriteGuard)
1070            }
1071            #[inline(always)]
1072            /// if the lazy is not already read or write locked: get a write lock if the lazy is
1073            /// initialized or an [AccessError] . Otherwise returns `None`
1074            pub fn fast_try_write(&self) ->
1075               Option<Result<WriteGuard<'_,T>,AccessError>> {
1076               GenericLockedLazy::fast_try_write_lock(unsafe{as_static(&self.__private)}).map(|r| r.map(WriteGuard))
1077            }
1078            #[inline(always)]
1079            /// Initialize the lazy if no previous attempt to initialized it where performed
1080            pub fn init(&self) -> Phase {
1081                let l = GenericLockedLazy::init_then_write_lock(unsafe{as_static(&self.__private)});
1082                Phased::phase(&l)
1083            }
1084        }
1085
1086    };
1087    (@lock_global $tp:ident, $checker:ident, $data:ty,$gdw:ident,$gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?) => {
1088
1089        use super::inited;
1090
1091        impl<T, G> $tp<T, G>
1092        //where $data: 'static + LazyData<Target=T>,
1093        where G: 'static + Generator<T>,
1094        T: 'static,
1095        $(G:$trg, T:Send,)?
1096        $(T:$tr,)?
1097        {
1098            #[inline(always)]
1099            /// Initialize if necessary and returns a read lock
1100            ///
1101            /// # Panic
1102            ///
1103            /// Panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
1104            pub fn read(&'static self) -> ReadGuard<'static,T> {
1105                if inited::global_inited_hint() {
1106                    let l = unsafe{GenericLockedLazy::read_lock_unchecked(&self.__private)};
1107                    assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(&l)));
1108                    ReadGuard(l)
1109                } else {
1110                    ReadGuard(GenericLockedLazy::init_then_read_lock(&self.__private))
1111                }
1112            }
1113            /// Initialize if necessary and returns some read lock if the lazy is not
1114            /// already write locked. If the lazy is already write locked it returns `None`
1115            ///
1116            /// # Panic
1117            ///
1118            /// If locks succeeds, panics if initialization panics or if initialization has panicked in a previous attempt to initialize.
1119            #[inline(always)]
1120            pub fn fast_read(&'static self) -> Option<ReadGuard<'static,T>> {
1121                if inited::global_inited_hint() {
1122                    let l = unsafe{GenericLockedLazy::fast_read_lock_unchecked(&self.__private)};
1123                    if let Some(l) = &l {
1124                        assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(l)));
1125                    }
1126                    l
1127                } else {
1128                    GenericLockedLazy::fast_init_then_read_lock(&self.__private)
1129                }.map(ReadGuard)
1130            }
1131            #[inline(always)]
1132            /// Get a read lock if the lazy is initialized or an [AccessError]
1133            pub fn try_read(&'static self) -> Result<ReadGuard<'static,T>,AccessError> {
1134                if inited::global_inited_hint() {
1135                    let l = unsafe{GenericLockedLazy::read_lock_unchecked(&self.__private)};
1136                    let p = Phased::phase(&l);
1137                    if <$checker::<G>>::initialized_is_accessible(p) {
1138                        Ok(l)
1139                    } else {
1140                        Err(AccessError{phase:p})
1141                    }
1142                } else {
1143                    GenericLockedLazy::try_read_lock(&self.__private)
1144                }.map(ReadGuard)
1145            }
1146            /// if the lazy is not already write locked: get a read lock if the lazy is initialized
1147            /// or an [AccessError]. Otherwise returns `None`
1148            #[inline(always)]
1149            pub fn fast_try_read(&'static self) -> Option<Result<ReadGuard<'static,T>,AccessError>> {
1150                if inited::global_inited_hint() {
1151                    let l = unsafe{GenericLockedLazy::fast_read_lock_unchecked(&self.__private)};
1152                    l.map(|l| {
1153                        let p = Phased::phase(&l);
1154                        if <$checker::<G>>::initialized_is_accessible(p) {
1155                            Ok(l)
1156                        } else {
1157                            Err(AccessError{phase:p})
1158                        }
1159                    })
1160                } else {
1161                    GenericLockedLazy::fast_try_read_lock(&self.__private)
1162                }.map(|r| r.map(ReadGuard))
1163            }
1164            /// Initialize if necessary and returns a write lock
1165            ///
1166            /// # Panic
1167            ///
1168            /// Panics if initialization panics or if initialization has panicked in a previous
1169            /// attempt to initialize.
1170            #[inline(always)]
1171            pub fn write(&'static self) -> WriteGuard<'static,T> {
1172                WriteGuard(if inited::global_inited_hint() {
1173                    let l = unsafe{GenericLockedLazy::write_lock_unchecked(&self.__private)};
1174                    assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(&l)));
1175                    l
1176                } else {
1177                    GenericLockedLazy::init_then_write_lock(&self.__private)
1178                })
1179            }
1180            /// Initialize if necessary and returns some write lock if the lazy is not
1181            /// already write locked. If the lazy is already read or write locked it returns `None`
1182            ///
1183            /// # Panic
1184            ///
1185            /// If locks succeeds, panics if initialization panics or if initialization has
1186            /// panicked in a previous attempt to initialize.
1187            #[inline(always)]
1188            pub fn fast_write(&'static self) -> Option<WriteGuard<'static,T>> {
1189                if inited::global_inited_hint() {
1190                    let l = unsafe{GenericLockedLazy::fast_write_lock_unchecked(&self.__private)};
1191                    if let Some(l) = &l {
1192                        assert!(<$checker::<G>>::initialized_is_accessible(Phased::phase(l)));
1193                    }
1194                    l
1195                } else {
1196                    GenericLockedLazy::fast_init_then_write_lock(&self.__private)
1197                }.map(WriteGuard)
1198            }
1199            /// Get a read lock if the lazy is initialized or an [AccessError]
1200            #[inline(always)]
1201            pub fn try_write(&'static self) -> Result<WriteGuard<'static,T>,AccessError> {
1202                if inited::global_inited_hint() {
1203                    let l = unsafe{GenericLockedLazy::write_lock_unchecked(&self.__private)};
1204                    let p = Phased::phase(&l);
1205                    if <$checker::<G>>::initialized_is_accessible(p) {
1206                        Ok(l)
1207                    } else {
1208                        Err(AccessError{phase:p})
1209                    }
1210                } else {
1211                    GenericLockedLazy::try_write_lock(&self.__private)
1212                }.map(WriteGuard)
1213            }
1214            /// if the lazy is not already read or write locked: get a write lock if the lazy is
1215            /// initialized or an [AccessError] . Otherwise returns `None`
1216            #[inline(always)]
1217            pub fn fast_try_write(&'static self) -> Option<Result<WriteGuard<'static,T>,AccessError>> {
1218                if inited::global_inited_hint() {
1219                    let l = unsafe{GenericLockedLazy::fast_write_lock_unchecked(&self.__private)};
1220                    l.map(|l| {
1221                        let p = Phased::phase(&l);
1222                        if <$checker::<G>>::initialized_is_accessible(p) {
1223                            Ok(l)
1224                        } else {
1225                            Err(AccessError{phase:p})
1226                        }
1227                    })
1228                } else {
1229                    GenericLockedLazy::fast_try_write_lock(&self.__private)
1230                }.map(|r| r.map(WriteGuard))
1231            }
1232            /// Initialize the lazy if no previous attempt to initialized it where performed
1233            #[inline(always)]
1234            pub fn init(&'static self) -> Phase {
1235                let l = GenericLockedLazy::init_then_write_lock(&self.__private);
1236                Phased::phase(&l)
1237            }
1238        }
1239
1240    };
1241    (@prime_static $tp:ident,$checker:ident, $data:ty, $gdw: ident, $gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?) => {
1242        impl<T, G> $tp<T, G>
1243        //where $data: 'static + LazyData<Target=T>,
1244        where G: 'static + Generator<T>,
1245        T: 'static,
1246        $(G:$trg, T:Send,)?
1247        $(T:$tr,)?
1248        {
1249            #[inline(always)]
1250            /// Return a read lock to the initialized value or an error containing a read lock to
1251            /// the primed or post uninited value
1252            pub fn primed_read_non_initializing(&'static self) ->
1253               Result<ReadGuard<'static,T>,ReadGuard<'static,T>> {
1254               let l = unsafe {GenericLockedLazy::read_lock_unchecked(&self.__private)};
1255               let p = Phased::phase(&l);
1256               if <$checker::<G>>::is_accessible(p) {
1257                   Ok(ReadGuard(l))
1258               } else {
1259                   Err(ReadGuard(l))
1260               }
1261            }
1262            #[inline(always)]
1263            /// Initialize if possible and either return a read lock to the initialized value or an
1264            /// error containing a read lock to the primed or post uninited value
1265            pub fn primed_read(&'static self) -> Result<ReadGuard<'static,T>,ReadGuard<'static,T>> {
1266               let l = unsafe {GenericLockedLazy::init_then_read_lock_unchecked(&self.__private)};
1267               let p = Phased::phase(&l);
1268               if <$checker::<G>>::is_accessible(p) {
1269                   Ok(ReadGuard(l))
1270               } else {
1271                   Err(ReadGuard(l))
1272               }
1273            }
1274            #[inline(always)]
1275            /// Return a write lock that refers to the initialized value or an
1276            /// error containing a read lock that refers to the primed or post uninited value
1277            pub fn primed_write_non_initializing(&'static self) -> Result<WriteGuard<'static,T>,ReadGuard<'static,T>> {
1278               let l = unsafe{GenericLockedLazy::write_lock_unchecked(&self.__private)};
1279               let p = Phased::phase(&l);
1280               if <$checker::<G>>::is_accessible(p) {
1281                   Ok(WriteGuard(l))
1282               } else {
1283                   Err(ReadGuard(l.into()))
1284               }
1285            }
1286            #[inline(always)]
1287            /// Initialize if possible and either return a write lock that refers to the
1288            /// initialized value or an error containing a read lock that refers to the primed or
1289            /// post uninited value
1290            pub fn primed_write(&'static self) -> Result<WriteGuard<'static,T>,ReadGuard<'static,T>> {
1291               let l = unsafe{GenericLockedLazy::init_then_write_lock_unchecked(&self.__private)};
1292               let p = Phased::phase(&l);
1293               if <$checker::<G>>::is_accessible(p) {
1294                   Ok(WriteGuard(l))
1295               } else {
1296                   Err(ReadGuard(l.into()))
1297               }
1298            }
1299        }
1300    };
1301    (@prime_global $tp:ident,$checker:ident, $data:ty, $gdw: ident, $gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?) => {
1302        impl<T, G> $tp<T, G>
1303        //where $data: 'static + LazyData<Target=T>,
1304        where G: 'static + Generator<T>,
1305        T: 'static,
1306        $(G:$trg, T:Send,)?
1307        $(T:$tr,)?
1308        {
1309            #[inline(always)]
1310            /// Return a read lock to the initialized value or an error containing a read lock to
1311            /// the primed or post uninited value
1312            pub fn primed_read_non_initializing(&'static self) ->
1313               Result<ReadGuard<'static,T>,ReadGuard<'static,T>> {
1314               let l = unsafe {GenericLockedLazy::read_lock_unchecked(&self.__private)};
1315               let p = Phased::phase(&l);
1316               if inited::global_inited_hint() {
1317                  if <$checker::<G>>::initialized_is_accessible(p) {
1318                      Ok(ReadGuard(l))
1319                  } else {
1320                      Err(ReadGuard(l))
1321                  }
1322               } else {
1323                  if <$checker::<G>>::is_accessible(p) {
1324                      Ok(ReadGuard(l))
1325                  } else {
1326                      Err(ReadGuard(l))
1327                  }
1328               }
1329            }
1330            #[inline(always)]
1331            /// Initialize if possible and either return a read lock to the initialized value or an
1332            /// error containing a read lock to the primed or post uninited value
1333            pub fn primed_read(&'static self) -> Result<ReadGuard<'static,T>,ReadGuard<'static,T>> {
1334               let l = unsafe {GenericLockedLazy::init_then_read_lock_unchecked(&self.__private)};
1335               let p = Phased::phase(&l);
1336               if inited::global_inited_hint() {
1337                  if <$checker::<G>>::initialized_is_accessible(p) {
1338                      Ok(ReadGuard(l))
1339                  } else {
1340                      Err(ReadGuard(l))
1341                  }
1342               } else {
1343                  if <$checker::<G>>::is_accessible(p) {
1344                      Ok(ReadGuard(l))
1345                  } else {
1346                      Err(ReadGuard(l))
1347                  }
1348               }
1349            }
1350            #[inline(always)]
1351            /// Return a write lock that refers to the initialized value or an
1352            /// error containing a read lock that refers to the primed or post uninited value
1353            pub fn primed_write_non_initializing(&'static self) -> Result<WriteGuard<'static,T>,ReadGuard<'static,T>> {
1354               let l = unsafe{GenericLockedLazy::write_lock_unchecked(&self.__private)};
1355               let p = Phased::phase(&l);
1356               if inited::global_inited_hint() {
1357                  if <$checker::<G>>::initialized_is_accessible(p) {
1358                      Ok(WriteGuard(l))
1359                  } else {
1360                      Err(ReadGuard(l.into()))
1361                  }
1362               } else {
1363                  if <$checker::<G>>::is_accessible(p) {
1364                      Ok(WriteGuard(l))
1365                  } else {
1366                      Err(ReadGuard(l.into()))
1367                  }
1368               }
1369            }
1370            #[inline(always)]
1371            /// Initialize if possible and either return a write lock that refers to the
1372            /// initialized value or an error containing a read lock that refers to the primed or
1373            /// post uninited value
1374            pub fn primed_write(&'static self) -> Result<WriteGuard<'static,T>,ReadGuard<'static,T>> {
1375               let l = unsafe{GenericLockedLazy::init_then_write_lock_unchecked(&self.__private)};
1376               let p = Phased::phase(&l);
1377               if inited::global_inited_hint() {
1378                  if <$checker::<G>>::initialized_is_accessible(p) {
1379                      Ok(WriteGuard(l))
1380                  } else {
1381                      Err(ReadGuard(l.into()))
1382                  }
1383               } else {
1384                  if <$checker::<G>>::is_accessible(p) {
1385                      Ok(WriteGuard(l))
1386                  } else {
1387                      Err(ReadGuard(l.into()))
1388                  }
1389               }
1390            }
1391        }
1392    };
1393    (@prime_thread_local $tp:ident,$checker:ident, $data:ty, $gdw: ident, $gd:ident$(,T: $tr: ident)?$(,G: $trg:ident)?) => {
1394        impl<T, G> $tp<T, G>
1395        //where $data: 'static + LazyData<Target=T>,
1396        where G: 'static + Generator<T>,
1397        T:'static,
1398        $(G:$trg, T:Send,)?
1399        $(T:$tr,)?
1400        {
1401            #[inline(always)]
1402            /// Return a read lock to the initialized value or an
1403            /// error containing a read lock to the primed or post uninited value
1404            pub fn primed_read_non_initializing(&self) -> Result<ReadGuard<'_,T>,ReadGuard<'_,T>> {
1405               let l = unsafe{GenericLockedLazy::read_lock_unchecked(as_static(&self.__private))};
1406               let p = Phased::phase(&l);
1407               if <$checker::<G>>::is_accessible(p) {
1408                   Ok(ReadGuard(l))
1409               } else {
1410                   Err(ReadGuard(l))
1411               }
1412            }
1413            #[inline(always)]
1414            /// Initialize if possible and either return a read lock to the initialized value or an
1415            /// error containing a read lock to the primed or post uninited value
1416            pub fn primed_read(&self) -> Result<ReadGuard<'_,T>,ReadGuard<'_,T>> {
1417               let l = unsafe{GenericLockedLazy::init_then_read_lock_unchecked(as_static(&self.__private))};
1418               let p = Phased::phase(&l);
1419               if <$checker::<G>>::is_accessible(p) {
1420                   Ok(ReadGuard(l))
1421               } else {
1422                   Err(ReadGuard(l))
1423               }
1424            }
1425            #[inline(always)]
1426            /// Return a write lock that refers to the initialized value or an
1427            /// error containing a read lock that refers to the primed or post uninited value
1428            pub fn primed_write_non_initializing(&self) -> Result<WriteGuard<'_,T>,ReadGuard<'_,T>> {
1429               let l = unsafe{GenericLockedLazy::write_lock_unchecked(as_static(&self.__private))};
1430               let p = Phased::phase(&l);
1431               if <$checker::<G>>::is_accessible(p) {
1432                   Ok(WriteGuard(l))
1433               } else {
1434                   Err(ReadGuard(l.into()))
1435               }
1436            }
1437            #[inline(always)]
1438            /// Initialize if possible and either return a write lock that refers to the initialized value or an
1439            /// error containing a read lock that refers to the primed or post uninited value
1440            pub fn primed_write(&self) -> Result<WriteGuard<'_,T>,ReadGuard<'_,T>> {
1441               let l = unsafe{GenericLockedLazy::init_then_write_lock_unchecked(as_static(&self.__private))};
1442               let p = Phased::phase(&l);
1443               if <$checker::<G>>::is_accessible(p) {
1444                   Ok(WriteGuard(l))
1445               } else {
1446                   Err(ReadGuard(l.into()))
1447               }
1448            }
1449        }
1450    };
1451    (@uninited $tp:ident, $man:ident$(<$x:ident>)?, $data:ty, $locker: ty$(,$safe:ident)?) => {
1452        impl<T, G> $tp<T, G> {
1453            #[inline(always)]
1454            /// Build a new static object.
1455            ///
1456            /// # Safety
1457            ///
1458            /// This function may be unsafe if build this object as anything else than
1459            /// a static or a thread local static would be the cause of undefined behavior
1460            pub const $($safe)? fn from_generator(f: G) -> Self {
1461                #[allow(unused_unsafe)]
1462                Self {
1463
1464                    __private: unsafe{GenericLockedLazy::new(f, $man::new(<$locker>::new(Phase::empty())),<$data>::INIT)},
1465                }
1466            }
1467            #[inline(always)]
1468            /// Build a new static object with debug informations.
1469            ///
1470            /// # Safety
1471            ///
1472            /// This function may be unsafe if build this object as anything else than
1473            /// a static or a thread local static would be the cause of undefined behavior
1474            pub const $($safe)?  fn from_generator_with_info(f: G, info: StaticInfo) -> Self {
1475                #[allow(unused_unsafe)]
1476                Self {
1477                    __private: unsafe{GenericLockedLazy::new_with_info(f, $man::new(<$locker>::new(Phase::empty())), <$data>::INIT,info)},
1478                }
1479            }
1480        }
1481    };
1482    (@prime $tp:ident, $man:ident$(<$x:ident>)?, $data:ty, $locker: ty $(,$safe:ident)?) => {
1483        impl<T, G> $tp<T, G> {
1484            #[inline(always)]
1485            /// Build a new static object.
1486            ///
1487            /// # Safety
1488            ///
1489            /// This function may be unsafe if build this object as anything else than
1490            /// a static or a thread local static would be the cause of undefined behavior
1491            pub const $($safe)? fn from_generator(v: T, f: G) -> Self {
1492                #[allow(unused_unsafe)]
1493                Self {
1494
1495                    __private: unsafe{GenericLockedLazy::new(f, $man::new(<$locker>::new(Phase::empty())),<$data>::prime(v))},
1496                }
1497            }
1498            #[inline(always)]
1499            /// Build a new static object with debug informations.
1500            ///
1501            /// # Safety
1502            ///
1503            /// This function may be unsafe if build this object as anything else than
1504            /// a static or a thread local static would be the cause of undefined behavior
1505            pub const $($safe)?  fn from_generator_with_info(v: T, f: G, info: StaticInfo) -> Self {
1506                #[allow(unused_unsafe)]
1507                Self {
1508                    __private: unsafe{GenericLockedLazy::new_with_info(f, $man::new(<$locker>::new(Phase::empty())), <$data>::prime(v),info)},
1509                }
1510            }
1511        }
1512    };
1513    (@proc $tp:ident, $man:ident$(<$x:ident>)?, $checker:ident, $data:ty, $locker: ty, $gdw: ident, $gd:ident $(,T: $tr: ident)?$(,G: $trg:ident)?
1514    ,$doc:literal $(cfg($attr:meta))? $(,$safe:ident)? $(,$static:lifetime)?) => {
1515        #[doc=$doc]
1516        $(#[cfg_attr(docsrs,doc(cfg($attr)))])?
1517        pub struct $tp<T, G = fn() -> T> {
1518            __private: GenericLockedLazy<$data, G, $man$(<$x>)?, $checker::<G>>,
1519        }
1520
1521        #[must_use="If unused the write lock is immediatly released"]
1522        #[derive(Debug)]
1523        pub struct WriteGuard<'a,T>(generic_lazy::WriteGuard<$gdw::<'a,$data>>);
1524
1525        #[must_use="If unused the write lock is immediatly released"]
1526        #[derive(Debug)]
1527        pub struct ReadGuard<'a,T>(generic_lazy::ReadGuard<$gd::<'a,$data>>);
1528
1529        impl<'a,T> Clone for ReadGuard<'a,T> {
1530            #[inline(always)]
1531            fn clone(&self) -> Self {
1532                Self(self.0.clone())
1533            }
1534        }
1535        impl<'a,T> From<WriteGuard<'a,T>> for ReadGuard<'a,T> {
1536            #[inline(always)]
1537            fn from(that:WriteGuard<'a,T>) -> Self {
1538                Self(that.0.into())
1539            }
1540        }
1541
1542        use core::ops::{Deref,DerefMut};
1543
1544        impl<'a,T> Deref for WriteGuard<'a,T>
1545        $(where T: $static)?
1546        {
1547            type Target = T;
1548            #[inline(always)]
1549            fn deref(&self) -> &T {
1550                &*self.0
1551            }
1552        }
1553        impl<'a,T> DerefMut for WriteGuard<'a,T>
1554        $(where T: $static)?
1555        {
1556            #[inline(always)]
1557            fn deref_mut(&mut self) -> &mut T {
1558                &mut *self.0
1559            }
1560        }
1561        impl<'a,T> Deref for ReadGuard<'a,T>
1562        $(where T: $static)?
1563        {
1564            type Target = T;
1565            #[inline(always)]
1566            fn deref(&self) -> &T {
1567                &*self.0
1568            }
1569        }
1570
1571        impl<'a, T> Phased for ReadGuard<'a,T>
1572        $(where T: $static)?
1573        {
1574            #[inline(always)]
1575            fn phase(this: &Self) -> Phase {
1576                Phased::phase(&this.0)
1577            }
1578        }
1579
1580        impl<'a, T> Phased for WriteGuard<'a,T>
1581        $(where T: $static)?
1582        {
1583            #[inline(always)]
1584            fn phase(this: &Self) -> Phase {
1585                Phased::phase(&this.0)
1586            }
1587        }
1588
1589        impl<T, G> Phased for $tp<T, G>
1590        where
1591        $(T: $static ,)?
1592        G: $($static +)? Generator<T>
1593        {
1594            #[inline(always)]
1595            fn phase(this: &Self) -> Phase {
1596                Phased::phase(&this.__private)
1597            }
1598        }
1599
1600        impl<T, G> $tp<T, G>
1601        where
1602        $(T: $static ,)?
1603        G: $($static +)? Generator<T>,
1604        $(G:$trg, T:Send,)?
1605        $(T:$tr,)?
1606        {
1607            #[inline(always)]
1608            /// Returns the current phase and synchronize with the end
1609            /// of the transition to the returned phase.
1610            pub fn phase(&$($static)? self) -> Phase {
1611                Phased::phase(&self.__private)
1612            }
1613        }
1614    };
1615}
1616
1617impl_mut_lazy! {locked_lazy:extend_locked_lazy, LockedLazy,SyncSequentializer<G>,InitializedChecker,UnInited::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,
1618"A mutable locked lazy that initialize its content on the first lock"}
1619
1620impl_mut_lazy! {global lesser_locked_lazy, LesserLockedLazy,SyncSequentializer<G>,InitializedChecker,UnInited::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,
1621"The actual type of mutable statics attributed with [#[dynamic]](macro@crate::dynamic) \
1622\
1623The method [from_generator](Self::from_generator) is unsafe because this kind of static \
1624can only safely be used through this attribute macros."
1625}
1626
1627impl_mut_lazy! {primed_static primed_locked_lazy, PrimedLockedLazy,SyncSequentializer<G>,InitializedChecker,Primed::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,
1628"The actual type of mutable statics attributed with [#[dynamic(primed)]](macro@crate::dynamic)"}
1629
1630impl_mut_lazy! {global_primed_static primed_lesser_locked_lazy, PrimedLesserLockedLazy,SyncSequentializer<G>,InitializedChecker,Primed::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,
1631"The actual type of mutable statics attributed with [#[dynamic(primed)]](macro@crate::dynamic)"}
1632
1633impl_mut_lazy! {static locked_lazy_finalize,LockedLazyFinalize,ExitSequentializer<G>,InitializedSoftFinalizedChecker,UnInited::<T>,SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard, T:Finaly,G:Sync,
1634"The actual type of mutable statics attributed with [#[dynamic(lazy,finalize)]](macro@crate::dynamic)"
1635}
1636
1637impl_mut_lazy! {global lesser_locked_lazy_finalize,LesserLockedLazyFinalize,ExitSequentializer<G>,InitializedSoftFinalizedCheckerLesser,UnInited::<T>,SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,T:Finaly, G:Sync,
1638"The actual type of mutable statics attributed with [#[dynamic(finalize)]](macro@crate::dynamic) \
1639\
1640The method [from_generator](Self::from_generator) is unsafe because this kind of static \
1641can only safely be used through this attribute macros."
1642}
1643impl_mut_lazy! {static locked_lazy_droped,LockedLazyDroped,ExitSequentializer<G>,InitializedHardFinalizedChecker,DropedUnInited::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,G:Sync,
1644"The actual type of statics attributed with [#[dynamic(lazy,finalize)]](macro@crate::dynamic)"
1645}
1646
1647impl_mut_lazy! {global lesser_locked_lazy_droped,LesserLockedLazyDroped,ExitSequentializer<G>,InitializedHardFinalizedCheckerLesser,DropedUnInited::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,G:Sync,
1648"The actual type of mutable statics attributed with #[dynamic(drop)] \
1649\
1650The method (new)[Self::from_generator] is unsafe because this kind of static \
1651can only safely be used through this attribute macros."
1652}
1653
1654impl_mut_lazy! {primed_static primed_locked_lazy_droped,PrimedLockedLazyDroped,ExitSequentializer<G>,InitializedHardFinalizedChecker,Primed::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,T:Uninit, G:Sync,
1655"The actual type of mutable statics attributed with [#[dynamic(primed,drop)]](macro@crate::dynamic)"
1656}
1657
1658impl_mut_lazy! {global_primed_static global_primed_locked_lazy_droped,PrimedLesserLockedLazyDroped,ExitSequentializer<G>,InitializedHardFinalizedChecker,Primed::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,T:Uninit, G:Sync,
1659"The actual type of mutable statics attributed with [#[dynamic(primed,drop)]](macro@crate::dynamic)"
1660}
1661
1662//impl_mut_lazy! {const_static const_locked_lazy_droped, ConstLockedLazyDroped,ExitSequentializer<G>,InitializedSoftFinalizedChecker,Primed::<T>, SyncPhaseLocker, SyncPhaseGuard, SyncReadPhaseGuard,G:Sync,
1663//"The actual type of statics (non mutable) attributed with [#[dynamic(lazy,drop)]](macro@crate::dynamic)"
1664//}
1665
1666impl_mut_lazy! {unsync_locked_lazy:extend_unsync_locked_lazy,UnSyncLockedLazy,UnSyncSequentializer<G>,InitializedChecker,UnInited::<T>,UnSyncPhaseLocker, UnSyncPhaseGuard,UnSyncReadPhaseGuard,
1667"A RefCell that initializes its content on the first access"
1668}
1669
1670#[cfg(feature = "thread_local")]
1671impl_mut_lazy! {primed_thread_local unsync_primed_locked_lazy,UnSyncPrimedLockedLazy,UnSyncSequentializer<G>,InitializedChecker,Primed::<T>,UnSyncPhaseLocker, UnSyncPhaseGuard,UnSyncReadPhaseGuard,
1672"The actual type of mutable thread_local statics attributed with [#[dynamic(primed)]](macro@crate::dynamic) \
1673\
1674The method [from_generator](Self::from_generator)  is unsafe as the object must be a non mutable thread_local static." cfg(feature="thread_local")
1675}
1676#[cfg(feature = "thread_local")]
1677impl_mut_lazy! {primed_thread_local unsync_primed_locked_lazy_droped,UnSyncPrimedLockedLazyDroped,ThreadExitSequentializer<G>,InitializedHardFinalizedTLChecker,Primed::<T>,UnSyncPhaseLocker, UnSyncPhaseGuard,UnSyncReadPhaseGuard, T:Uninit,
1678"The actual type of mutable thread_local statics attributed with [#[dynamic(primed,drop)]](macro@crate::dynamic) \
1679\
1680The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable thread_local static." cfg(feature="thread_local")
1681}
1682
1683#[cfg(feature = "thread_local")]
1684impl_mut_lazy! {thread_local unsync_locked_lazy_finalize,UnSyncLockedLazyFinalize,ThreadExitSequentializer<G>,InitializedSoftFinalizedTLChecker,UnInited::<T>,UnSyncPhaseLocker, UnSyncPhaseGuard,UnSyncReadPhaseGuard,T:Finaly,
1685"The actual type of mutable thread_local statics attributed with [#[dynamic(finalize)]](macro@crate::dynamic) \
1686\
1687The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable thread_local static." cfg(feature="thread_local")
1688}
1689#[cfg(feature = "thread_local")]
1690impl_mut_lazy! {thread_local unsync_locked_lazy_droped,UnSyncLockedLazyDroped,ThreadExitSequentializer<G>,InitializedHardFinalizedTLChecker,DropedUnInited::<T>,UnSyncPhaseLocker, UnSyncPhaseGuard,UnSyncReadPhaseGuard,
1691"The actual type of thread_local mutable statics attributed with [#[dynamic(drop)]](macro@crate::dynamic) \
1692\
1693The method [from_generator](Self::from_generator) is unsafe as the object must be a non mutable thread_local static." cfg(feature="thread_local")
1694}
1695
1696#[cfg(all(support_priority, not(feature = "test_no_global_lazy_hint")))]
1697mod inited {
1698
1699    use core::sync::atomic::{AtomicBool, Ordering};
1700
1701    static LAZY_INIT_ENSURED: AtomicBool = AtomicBool::new(false);
1702
1703    #[static_init_macro::constructor(__lazy_init_finished)]
1704    extern "C" fn mark_inited() {
1705        LAZY_INIT_ENSURED.store(true, Ordering::Release);
1706    }
1707
1708    #[inline(always)]
1709    pub(super) fn global_inited_hint() -> bool {
1710        LAZY_INIT_ENSURED.load(Ordering::Acquire)
1711    }
1712}
1713#[cfg(not(all(support_priority, not(feature = "test_no_global_lazy_hint"))))]
1714mod inited {
1715    #[inline(always)]
1716    pub(super) const fn global_inited_hint() -> bool {
1717        false
1718    }
1719}
1720
1721#[cfg(test)]
1722mod test_lazy {
1723    use super::Lazy;
1724    static _X: Lazy<u32, fn() -> u32> = Lazy::from_generator(|| 22);
1725
1726    #[test]
1727    fn test() {
1728        assert_eq!(*_X, 22);
1729    }
1730}
1731
1732#[cfg(feature = "test_no_global_lazy_hint")]
1733#[cfg(test)]
1734mod test_quasi_lazy {
1735    use super::LesserLazy;
1736    static _X: LesserLazy<u32, fn() -> u32> = unsafe { LesserLazy::from_generator(|| 22) };
1737    #[test]
1738    fn test() {
1739        assert_eq!(*_X, 22);
1740    }
1741}
1742#[cfg(all(test, feature = "thread_local"))]
1743mod test_local_lazy {
1744    use super::UnSyncLazy;
1745    #[thread_local]
1746    static _X: UnSyncLazy<u32, fn() -> u32> = UnSyncLazy::from_generator(|| 22);
1747    #[test]
1748    fn test() {
1749        assert_eq!(*_X, 22);
1750    }
1751}
1752#[cfg(test)]
1753mod test_lazy_finalize {
1754    use super::LazyFinalize;
1755    use crate::Finaly;
1756    #[derive(Debug)]
1757    struct A(u32);
1758    impl Finaly for A {
1759        fn finaly(&self) {}
1760    }
1761    static _X: LazyFinalize<A, fn() -> A> = unsafe { LazyFinalize::from_generator(|| A(22)) };
1762    #[test]
1763    fn test() {
1764        assert_eq!(_X.0, 22);
1765    }
1766}
1767#[cfg(feature = "test_no_global_lazy_hint")]
1768#[cfg(test)]
1769mod test_quasi_lazy_finalize {
1770    use super::LesserLazyFinalize;
1771    use crate::Finaly;
1772    #[derive(Debug)]
1773    struct A(u32);
1774    impl Finaly for A {
1775        fn finaly(&self) {}
1776    }
1777    static _X: LesserLazyFinalize<A, fn() -> A> =
1778        unsafe { LesserLazyFinalize::from_generator(|| A(22)) };
1779    #[test]
1780    fn test() {
1781        assert_eq!((*_X).0, 22);
1782    }
1783}
1784#[cfg(all(test, feature = "thread_local"))]
1785mod test_local_lazy_finalize {
1786    use super::UnSyncLazyFinalize;
1787    use crate::Finaly;
1788    #[derive(Debug)]
1789    struct A(u32);
1790    impl Finaly for A {
1791        fn finaly(&self) {}
1792    }
1793    #[thread_local]
1794    static _X: UnSyncLazyFinalize<A, fn() -> A> =
1795        unsafe { UnSyncLazyFinalize::from_generator(|| A(22)) };
1796    #[test]
1797    fn test() {
1798        assert_eq!(_X.0, 22);
1799    }
1800}
1801#[cfg(all(test, feature = "thread_local"))]
1802mod test_droped_local_lazy_finalize {
1803    use super::UnSyncLazyDroped;
1804    #[derive(Debug)]
1805    struct A(u32);
1806    #[thread_local]
1807    static _X: UnSyncLazyDroped<A> = unsafe { UnSyncLazyDroped::from_generator(|| A(22)) };
1808    #[test]
1809    fn test() {
1810        assert_eq!(_X.0, 22);
1811    }
1812}
1813
1814#[cfg(test)]
1815mod test_mut_lazy {
1816    use super::LockedLazy;
1817    static _X: LockedLazy<u32, fn() -> u32> = LockedLazy::from_generator(|| 22);
1818    #[test]
1819    fn test() {
1820        assert_eq!(*_X.read(), 22);
1821        *_X.write() = 33;
1822        assert_eq!(*_X.read(), 33);
1823    }
1824}
1825
1826#[cfg(test)]
1827mod test_primed_mut_lazy_droped {
1828    use super::PrimedLockedLazyDroped;
1829    use crate::Uninit;
1830    #[derive(Debug)]
1831    struct A(u32);
1832    impl Uninit for A {
1833        fn uninit(&mut self) {
1834            self.0 = 0
1835        }
1836    }
1837    static _X: PrimedLockedLazyDroped<A> = PrimedLockedLazyDroped::from_generator(A(42), || A(22));
1838    #[test]
1839    fn test() {
1840        assert_eq!(_X.primed_read_non_initializing().unwrap_err().0, 42);
1841        assert_eq!(_X.read().0, 22);
1842        _X.write().0 = 33;
1843        assert_eq!(_X.read().0, 33);
1844    }
1845}
1846
1847#[cfg(test)]
1848mod test_primed_mut_lazy {
1849    use super::PrimedLockedLazy;
1850    static _X: PrimedLockedLazy<u32> = PrimedLockedLazy::from_generator(42, || 22);
1851    #[test]
1852    fn test() {
1853        assert_eq!(*_X.primed_read_non_initializing().unwrap_err(), 42);
1854        assert_eq!(*_X.read(), 22);
1855        *_X.write() = 33;
1856        assert_eq!(*_X.read(), 33);
1857    }
1858}
1859
1860#[cfg(feature = "test_no_global_lazy_hint")]
1861#[cfg(test)]
1862mod test_quasi_mut_lazy {
1863    use super::LesserLockedLazy;
1864    static _X: LesserLockedLazy<u32, fn() -> u32> =
1865        unsafe { LesserLockedLazy::from_generator(|| 22) };
1866    #[test]
1867    fn test() {
1868        assert_eq!(*_X.read(), 22);
1869        *_X.write() = 33;
1870        assert_eq!(*_X.read(), 33);
1871    }
1872}
1873#[cfg(test)]
1874mod test_mut_lazy_finalize {
1875    use super::LockedLazyFinalize;
1876    use crate::Finaly;
1877    #[derive(Debug)]
1878    struct A(u32);
1879    impl Finaly for A {
1880        fn finaly(&self) {}
1881    }
1882    static _X: LockedLazyFinalize<A, fn() -> A> = LockedLazyFinalize::from_generator(|| A(22));
1883    #[test]
1884    fn test() {
1885        assert!((*_X.read()).0 == 22);
1886        *_X.write() = A(33);
1887        assert_eq!((*_X.read()).0, 33);
1888    }
1889}
1890#[cfg(feature = "test_no_global_lazy_hint")]
1891#[cfg(test)]
1892mod test_quasi_mut_lazy_finalize {
1893    use super::LesserLockedLazyFinalize;
1894    use crate::Finaly;
1895    #[derive(Debug)]
1896    struct A(u32);
1897    impl Finaly for A {
1898        fn finaly(&self) {}
1899    }
1900    static _X: LesserLockedLazyFinalize<A, fn() -> A> =
1901        unsafe { LesserLockedLazyFinalize::from_generator(|| A(22)) };
1902    #[test]
1903    fn test() {
1904        assert!((*_X.read()).0 == 22);
1905        *_X.write() = A(33);
1906        assert_eq!((*_X.read()).0, 33);
1907    }
1908}
1909#[cfg(test)]
1910mod test_mut_lazy_dropped {
1911    use super::LockedLazyDroped;
1912    static _X: LockedLazyDroped<u32, fn() -> u32> = LockedLazyDroped::from_generator(|| 22);
1913    #[test]
1914    fn test() {
1915        assert_eq!(*_X.read(), 22);
1916        *_X.write() = 33;
1917        assert_eq!(*_X.read(), 33);
1918    }
1919}
1920#[cfg(feature = "test_no_global_lazy_hint")]
1921#[cfg(test)]
1922mod test_quasi_mut_lazy_dropped {
1923    use super::LesserLockedLazyDroped;
1924    static _X: LesserLockedLazyDroped<u32, fn() -> u32> =
1925        unsafe { LesserLockedLazyDroped::from_generator(|| 22) };
1926    #[test]
1927    fn test() {
1928        assert_eq!(*_X.read(), 22);
1929        *_X.write() = 33;
1930        assert_eq!(*_X.read(), 33);
1931    }
1932}
1933#[cfg(test)]
1934#[cfg(feature = "thread_local")]
1935mod test_unsync_mut_lazy {
1936    use super::UnSyncLockedLazy;
1937    #[thread_local]
1938    static _X: UnSyncLockedLazy<u32, fn() -> u32> = UnSyncLockedLazy::from_generator(|| 22);
1939    #[test]
1940    fn test() {
1941        assert_eq!(*_X.read(), 22);
1942        *_X.write() = 33;
1943        assert_eq!(*_X.read(), 33);
1944    }
1945}
1946
1947#[cfg(test)]
1948#[cfg(feature = "thread_local")]
1949mod test_unsync_mut_primed_lazy {
1950    use super::UnSyncPrimedLockedLazy;
1951    #[thread_local]
1952    static _X: UnSyncPrimedLockedLazy<u32> =
1953        unsafe { UnSyncPrimedLockedLazy::from_generator(42, || 22) };
1954    #[test]
1955    fn test() {
1956        assert_eq!(*_X.primed_read_non_initializing().unwrap_err(), 42);
1957        assert_eq!(*_X.read(), 22);
1958        *_X.write() = 33;
1959        assert_eq!(*_X.read(), 33);
1960    }
1961}
1962#[cfg(test)]
1963#[cfg(feature = "thread_local")]
1964mod test_unsync_mut_primed_lazy_droped {
1965    use super::UnSyncPrimedLockedLazyDroped;
1966    use crate::Uninit;
1967    #[derive(Debug)]
1968    struct A(u32);
1969    impl Uninit for A {
1970        fn uninit(&mut self) {
1971            self.0 = 0
1972        }
1973    }
1974    #[thread_local]
1975    static _X: UnSyncPrimedLockedLazyDroped<A> =
1976        unsafe { UnSyncPrimedLockedLazyDroped::from_generator(A(42), || A(22)) };
1977    #[test]
1978    fn test() {
1979        assert_eq!(_X.primed_read_non_initializing().unwrap_err().0, 42);
1980        assert_eq!(_X.read().0, 22);
1981        _X.write().0 = 33;
1982        assert_eq!(_X.read().0, 33);
1983    }
1984}
1985
1986#[cfg(test)]
1987#[cfg(feature = "thread_local")]
1988mod test_unsync_mut_lazy_finalize {
1989    use super::UnSyncLockedLazyFinalize;
1990    use crate::Finaly;
1991    #[derive(Debug)]
1992    struct A(u32);
1993    impl Finaly for A {
1994        fn finaly(&self) {}
1995    }
1996    #[thread_local]
1997    static _X: UnSyncLockedLazyFinalize<A, fn() -> A> =
1998        unsafe { UnSyncLockedLazyFinalize::from_generator(|| A(22)) };
1999    #[test]
2000    fn test() {
2001        assert!((*_X.read()).0 == 22);
2002        *_X.write() = A(33);
2003        assert_eq!((*_X.read()).0, 33);
2004    }
2005}
2006#[cfg(test)]
2007#[cfg(feature = "thread_local")]
2008mod test_unsync_mut_lazy_droped {
2009    use super::UnSyncLockedLazyDroped;
2010    #[thread_local]
2011    static _X: UnSyncLockedLazyDroped<u32, fn() -> u32> =
2012        unsafe { UnSyncLockedLazyDroped::from_generator(|| 22) };
2013    #[test]
2014    fn test() {
2015        assert_eq!(*_X.read(), 22);
2016        *_X.write() = 33;
2017        assert_eq!(*_X.read(), 33);
2018    }
2019}
2020
2021#[inline(always)]
2022/// # Safety
2023/// v must refer to a static
2024unsafe fn as_static<T>(v: &T) -> &'static T {
2025    &*(v as *const _)
2026}