static_init/
generic_lazy.rs

1#![allow(unused)] //functions that are usefull for extension
2
3use crate::{
4    Finaly, Generator, LazySequentializer, LockNature, LockResult, Phase, Phased, Sequential,
5    Sequentializer, StaticInfo, Uninit, UniqueLazySequentializer,
6};
7use core::cell::UnsafeCell;
8use core::fmt::{self, Debug, Display, Formatter};
9use core::hint::unreachable_unchecked;
10use core::marker::PhantomData;
11use core::mem::MaybeUninit;
12use core::ops::{Deref, DerefMut};
13
14#[cfg(debug_mode)]
15use crate::CyclicPanic;
16
17#[cfg(any(feature = "parking_lot_core", debug_mode))]
18use std::panic::RefUnwindSafe;
19
20/// Policy for lazy initialization
21pub(crate) trait LazyPolicy {
22    /// shall the initialization be performed (tested at each access)
23    fn shall_init(_: Phase) -> bool;
24    /// Is the object accessible in phase `p`
25    fn is_accessible(p: Phase) -> bool;
26    /// Is the object accessible in phase `p`
27    fn post_init_is_accessible(p: Phase) -> bool;
28    /// If the object is known to already be initialized, is the object accessible in phase `p`
29    fn initialized_is_accessible(p: Phase) -> bool;
30}
31
32/// Generic lazy interior data storage, uninitialized with interior mutability data storage
33/// that call T::finaly when finalized
34pub(crate) struct UnInited<T>(UnsafeCell<MaybeUninit<T>>);
35
36impl<T: Finaly> Finaly for UnInited<T> {
37    #[inline(always)]
38    fn finaly(&self) {
39        //SAFETY: UnInited is only used as part of GenericLazy, that gives access
40        //only if the Sequentializer is a Lazy Sequentializer
41        //
42        //So the lazy Sequentializer should only execute finaly if the object initialization
43        //succeeded
44        unsafe { &*self.get() }.finaly();
45    }
46}
47
48impl<T> UnInited<T> {
49    pub const INIT: Self = Self(UnsafeCell::new(MaybeUninit::uninit()));
50}
51
52/// Generic lazy interior data storage, initialized with interior mutability data storage
53/// that call T::finaly when finalized
54pub(crate) struct Primed<T>(UnsafeCell<T>);
55
56impl<T: Uninit> Finaly for Primed<T> {
57    #[inline(always)]
58    fn finaly(&self) {
59        //SAFETY: UnInited is only used as part of GenericLazy, that gives access
60        //only if the Sequentializer is a Lazy Sequentializer
61        //
62        //So the lazy Sequentializer should only execute finaly if the object initialization
63        //succeeded
64        unsafe { &mut *self.0.get() }.uninit();
65    }
66}
67
68impl<T> Primed<T> {
69    pub const fn prime(v: T) -> Self {
70        Self(UnsafeCell::new(v))
71    }
72}
73
74/// Generic lazy interior data storage, uninitialized with interior mutability data storage
75/// that call drop when finalized
76pub(crate) struct DropedUnInited<T>(UnsafeCell<MaybeUninit<T>>);
77
78impl<T> Finaly for DropedUnInited<T> {
79    #[inline(always)]
80    fn finaly(&self) {
81        //SAFETY: UnInited is only used as part of GenericLazy, that gives access
82        //only if the Sequentializer is a Lazy Sequentializer
83        //
84        //So the lazy Sequentializer should only execute finaly if the object initialization
85        //succeeded
86        unsafe { self.get().drop_in_place() };
87    }
88}
89
90impl<T> DropedUnInited<T> {
91    pub const INIT: Self = Self(UnsafeCell::new(MaybeUninit::uninit()));
92}
93
94/// Trait implemented by generic lazy inner data.
95///
96/// Dereferencement of generic lazy will return a reference to
97/// the inner data returned by the get method
98pub(crate) trait LazyData {
99    type Target;
100    fn get(&self) -> *mut Self::Target;
101    /// # Safety
102    ///
103    /// The reference to self should be unique
104    unsafe fn init(&self, v: Self::Target);
105    fn init_mut(&mut self, v: Self::Target);
106}
107
108impl<T> LazyData for UnInited<T> {
109    type Target = T;
110    #[inline(always)]
111    fn get(&self) -> *mut T {
112        self.0.get() as *mut T
113    }
114    #[inline(always)]
115    unsafe fn init(&self, v: T) {
116        self.get().write(v)
117    }
118    #[inline(always)]
119    fn init_mut(&mut self, v: T) {
120        *self.0.get_mut() = MaybeUninit::new(v)
121    }
122}
123
124impl<T> LazyData for DropedUnInited<T> {
125    type Target = T;
126    #[inline(always)]
127    fn get(&self) -> *mut T {
128        self.0.get() as *mut T
129    }
130    #[inline(always)]
131    unsafe fn init(&self, v: T) {
132        self.get().write(v)
133    }
134    #[inline(always)]
135    fn init_mut(&mut self, v: T) {
136        *self.0.get_mut() = MaybeUninit::new(v)
137    }
138}
139
140impl<T> LazyData for Primed<T> {
141    type Target = T;
142    #[inline(always)]
143    fn get(&self) -> *mut T {
144        self.0.get()
145    }
146    #[inline(always)]
147    unsafe fn init(&self, v: T) {
148        *self.get() = v
149    }
150    #[inline(always)]
151    fn init_mut(&mut self, v: T) {
152        *self.0.get_mut() = v
153    }
154}
155
156/// Lazy access error
157#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
158pub struct AccessError {
159    pub phase: Phase,
160}
161
162impl Display for AccessError {
163    fn fmt(&self, ft: &mut Formatter<'_>) -> fmt::Result {
164        write!(ft, "Error: inaccessible lazy in {}", self.phase)
165    }
166}
167
168#[cfg(feature = "parking_lot_core")]
169impl std::error::Error for AccessError {}
170
171pub(crate) struct GenericLazySeq<T, M> {
172    value: T,
173    sequentializer: M,
174}
175
176pub(crate) struct GenericLockedLazySeq<T, M> {
177    value: T,
178    sequentializer: M,
179}
180
181/// A type that wrap a Sequentializer and a raw data, and that may
182/// initialize the data, at each access depending on the LazyPolicy
183/// provided as generic argument.
184pub(crate) struct GenericLazy<T, F, M, S> {
185    seq: GenericLazySeq<T, M>,
186    generator: F,
187    phantom: PhantomData<S>,
188    #[cfg(debug_mode)]
189    _info: Option<StaticInfo>,
190}
191
192// SAFETY: The synchronization is ensured by the Sequentializer
193//  1. GenericLazy fullfill the requirement that its sequentializer is a field
194//  of itself as is its target data.
195//  2. The sequentializer ensure that the initialization is atomic
196unsafe impl<T: LazyData, M: Sync> Sync for GenericLazySeq<T, M> where <T as LazyData>::Target: Sync {}
197unsafe impl<T: LazyData, M: Sync> Send for GenericLazySeq<T, M> where <T as LazyData>::Target: Send {}
198
199#[cfg(any(feature = "parking_lot_core", debug_mode))]
200impl<T: LazyData, M: RefUnwindSafe> RefUnwindSafe for GenericLazySeq<T, M> where
201    <T as LazyData>::Target: RefUnwindSafe
202{
203}
204
205// SAFETY: The synchronization is ensured by the Sequentializer
206//  1. GenericLazy fullfill the requirement that its sequentializer is a field
207//  of itself as is its target data.
208//  2. The sequentializer ensure that the initialization is atomic
209unsafe impl<T: LazyData, M: Sync> Sync for GenericLockedLazySeq<T, M> where
210    <T as LazyData>::Target: Send
211{
212}
213unsafe impl<T: LazyData, M: Sync> Send for GenericLockedLazySeq<T, M> where
214    <T as LazyData>::Target: Send
215{
216}
217
218#[cfg(any(feature = "parking_lot_core", debug_mode))]
219impl<T: LazyData, M: RefUnwindSafe> RefUnwindSafe for GenericLockedLazySeq<T, M> where
220    <T as LazyData>::Target: RefUnwindSafe
221{
222}
223
224impl<T, F, M, S> GenericLazy<T, F, M, S> {
225    #[inline(always)]
226    /// const initialize the lazy, the inner data may be in an uninitialized state
227    ///
228    /// # Safety
229    ///
230    /// ## Constraint on T
231    ///
232    /// Should initialize the object when init is called and the method get should
233    /// return a pointer without UB if the object is not initialized
234    ///
235    /// ## Constraint on P
236    ///
237    /// The parameter M should be a lazy sequentializer that ensure that:
238    ///  1. When finalize is called, no other shared reference to the inner data exist
239    ///  2. The finalization is run only if the object was previously initialized
240    ///
241    /// ## Constraint on F
242    ///
243    /// The parameter F should be a Generator that ensured that the object
244    /// is accessble after a call to generate succeeds
245    ///
246    /// ## Constraint on S
247    ///
248    /// S should be a lazy policy that report correctly when the object
249    /// is accessbile, this in adequation with M and F.
250    pub const unsafe fn new(generator: F, sequentializer: M, value: T) -> Self {
251        Self {
252            seq: GenericLazySeq {
253                value,
254                sequentializer,
255            },
256            generator,
257            phantom: PhantomData,
258            #[cfg(debug_mode)]
259            _info: None,
260        }
261    }
262    #[inline(always)]
263    /// const initialize the lazy, the inner data may be in an uninitialized state
264    ///
265    /// # Safety
266    ///
267    /// ## Constraint on T
268    ///
269    /// Should initialize the object when init is called and the method get should
270    /// return a pointer without UB if the object is not initialized
271    ///
272    /// ## Constraint on P
273    ///
274    /// The parameter M should be a lazy sequentializer that ensure that:
275    ///  1. When finalize is called, no other shared reference to the inner data exist
276    ///  2. The finalization is run only if the object was previously initialized
277    ///
278    /// ## Constraint on F
279    ///
280    /// The parameter F should be a Generator that ensured that the object
281    /// is accessble after a call to generate succeeds
282    ///
283    /// ## Constraint on S
284    ///
285    /// S should be a lazy policy that report correctly when the object
286    /// is accessbile, this in adequation with M and F.
287    pub const unsafe fn new_with_info(
288        generator: F,
289        sequentializer: M,
290        value: T,
291        _info: StaticInfo,
292    ) -> Self {
293        Self {
294            seq: GenericLazySeq {
295                value,
296                sequentializer,
297            },
298            generator,
299            phantom: PhantomData,
300            #[cfg(debug_mode)]
301            _info: Some(_info),
302        }
303    }
304    #[inline(always)]
305    ///get access to the sequentializer
306    pub fn sequentializer(this: &Self) -> &M {
307        &this.seq.sequentializer
308    }
309    #[inline(always)]
310    ///get a pointer to the raw data
311    pub fn get_raw_data(this: &Self) -> &T {
312        &this.seq.value
313    }
314}
315impl<'a, T, F, M, S> GenericLazy<T, F, M, S>
316where
317    T: 'a + LazyData,
318    M: 'a,
319    M: LazySequentializer<'a, GenericLazySeq<T, M>>,
320    F: 'a + Generator<T::Target>,
321    S: 'a + LazyPolicy,
322{
323    /// Get a reference to the target
324    ///
325    /// # Safety
326    ///
327    /// Undefined behaviour if the referenced value has not been initialized
328    #[inline(always)]
329    pub unsafe fn get_unchecked(&'a self) -> &'a T::Target {
330        &*self.seq.value.get()
331    }
332
333    /// Get a reference to the target, returning an error if the
334    /// target is not in the correct phase.
335    #[inline(always)]
336    pub fn try_get(&'a self) -> Result<&'a T::Target, AccessError> {
337        check_access::<*mut T::Target, S>(
338            self.seq.value.get(),
339            Phased::phase(&self.seq.sequentializer),
340        )
341        .map(|ptr| unsafe { &*ptr })
342    }
343
344    /// Get a reference to the target
345    ///
346    /// # Panics
347    ///
348    /// Panic if the target is not in the correct phase
349    #[inline(always)]
350    pub fn get(&'a self) -> &'a T::Target {
351        self.try_get().unwrap()
352    }
353
354    /// Get a mutable reference to the target
355    ///
356    /// # Safety
357    ///
358    /// Undefined behaviour if the referenced value has not been initialized
359    #[inline(always)]
360    pub unsafe fn get_mut_unchecked(&'a mut self) -> &'a mut T::Target {
361        &mut *self.seq.value.get()
362    }
363
364    /// Get a mutable reference to the target, returning an error if the
365    /// target is not in the correct phase.
366    #[inline(always)]
367    pub fn try_get_mut(&'a mut self) -> Result<&'a mut T::Target, AccessError> {
368        check_access::<*mut T::Target, S>(
369            self.seq.value.get(),
370            Phased::phase(&self.seq.sequentializer),
371        )
372        .map(|ptr| unsafe { &mut *ptr })
373    }
374
375    /// Get a reference to the target
376    ///
377    /// # Panics
378    ///
379    /// Panic if the target is not in the correct phase
380    #[inline(always)]
381    pub fn get_mut(&'a mut self) -> &'a mut T::Target {
382        self.try_get_mut().unwrap()
383    }
384
385    /// Attempt initialization then get a reference to the target
386    ///
387    /// # Safety
388    ///
389    /// Undefined behaviour if the referenced value has not been initialized
390    #[inline(always)]
391    pub unsafe fn init_then_get_unchecked(&'a self) -> &'a T::Target {
392        self.init();
393        self.get_unchecked()
394    }
395    /// Attempt initialization then get a reference to the target, returning an error if the
396    /// target is not in the correct phase.
397    #[inline(always)]
398    pub fn init_then_try_get(&'a self) -> Result<&'a T::Target, AccessError> {
399        let phase = self.init();
400        post_init_check_access::<*mut T::Target, S>(self.seq.value.get(), phase)
401            .map(|ptr| unsafe { &*ptr })
402    }
403    /// Attempt initialization then get a reference to the target, returning an error if the
404    /// target is not in the correct phase.
405    #[inline(always)]
406    pub fn init_then_get(&'a self) -> &'a T::Target {
407        Self::init_then_try_get(self).unwrap()
408    }
409    #[inline(always)]
410    /// Potentialy initialize the inner data, returning the
411    /// phase reached at the end of the initialization attempt
412    pub fn init(&'a self) -> Phase {
413        may_debug(
414            || {
415                <M as LazySequentializer<'a, GenericLazySeq<T, M>>>::init(
416                    &self.seq,
417                    S::shall_init,
418                    |data: &T| {
419                        // SAFETY
420                        // This function is called only once within the init function
421                        // Only one thread can ever get this mutable access
422                        let d = Generator::generate(&self.generator);
423                        unsafe { data.init(d) };
424                    },
425                )
426            },
427            #[cfg(debug_mode)]
428            &self._info,
429        )
430    }
431}
432
433impl<T, F, M, S> GenericLazy<T, F, M, S>
434where
435    M: UniqueLazySequentializer<GenericLazySeq<T, M>>,
436    T: LazyData,
437    S: LazyPolicy,
438    F: Generator<T::Target>,
439{
440    #[inline(always)]
441    /// Attempt initialization then get a mutable reference to the target
442    ///
443    /// # Safety
444    ///
445    /// Undefined behaviour if the referenced value has not been initialized
446    pub unsafe fn only_init_then_get_mut_unchecked(&mut self) -> &mut T::Target {
447        self.only_init_unique();
448        &mut *self.seq.value.get()
449    }
450
451    #[inline(always)]
452    /// Attempt initialization then get a mutable reference to the target, returning an error if the
453    /// target is not in the correct phase.
454    pub fn only_init_then_try_get_mut(&mut self) -> Result<&mut T::Target, AccessError> {
455        let phase = self.only_init_unique();
456        post_init_check_access::<*mut T::Target, S>(self.seq.value.get(), phase)
457            .map(|ptr| unsafe { &mut *ptr })
458    }
459
460    #[inline(always)]
461    /// Attempt initialization then get a mutable reference to the target, returning an error if the
462    /// target is not in the correct phase.
463    pub fn only_init_then_get_mut(&mut self) -> &mut T::Target {
464        Self::only_init_then_try_get_mut(self).unwrap()
465    }
466
467    #[inline(always)]
468    /// Potentialy initialize the inner data, returning the
469    /// phase reached at the end of the initialization attempt
470    pub fn only_init_unique(&mut self) -> Phase {
471        let generator = &self.generator;
472        let seq = &mut self.seq;
473        <M as UniqueLazySequentializer<GenericLazySeq<T, M>>>::init_unique(
474            seq,
475            S::shall_init,
476            |data: &mut T| {
477                // SAFETY
478                // This function is called only once within the init function
479                // Only one thread can ever get this mutable access
480                let d = Generator::generate(generator);
481                unsafe { data.init_mut(d) };
482            },
483        )
484    }
485}
486
487//SAFETY: data and sequentialize are two fields of Self.
488unsafe impl<T: LazyData, M> Sequential for GenericLazySeq<T, M> {
489    type Data = T;
490    type Sequentializer = M;
491    #[inline(always)]
492    fn sequentializer(this: &Self) -> &Self::Sequentializer {
493        &this.sequentializer
494    }
495    #[inline(always)]
496    fn sequentializer_data_mut(this: &mut Self) -> (&mut Self::Sequentializer, &mut Self::Data) {
497        (&mut this.sequentializer, &mut this.value)
498    }
499    #[inline(always)]
500    fn data(this: &Self) -> &Self::Data {
501        &this.value
502    }
503}
504
505#[must_use = "If unused the write lock is immediatly released"]
506pub(crate) struct WriteGuard<T>(T);
507
508impl<T> Deref for WriteGuard<T>
509where
510    T: Deref,
511    <T as Deref>::Target: LazyData,
512{
513    type Target = <<T as Deref>::Target as LazyData>::Target;
514    #[inline(always)]
515    fn deref(&self) -> &Self::Target {
516        unsafe { &*(*self.0).get() }
517    }
518}
519impl<T> DerefMut for WriteGuard<T>
520where
521    T: Deref,
522    <T as Deref>::Target: LazyData,
523{
524    #[inline(always)]
525    fn deref_mut(&mut self) -> &mut Self::Target {
526        unsafe { &mut *(*self.0).get() }
527    }
528}
529
530impl<T> Phased for WriteGuard<T>
531where
532    T: Phased,
533{
534    #[inline(always)]
535    fn phase(this: &Self) -> Phase {
536        Phased::phase(&this.0)
537    }
538}
539
540impl<T> Debug for WriteGuard<T>
541where
542    T: Deref,
543    <T as Deref>::Target: LazyData,
544    <<T as Deref>::Target as LazyData>::Target: Debug,
545{
546    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
547        f.debug_tuple("WriteGuard").field(&*self).finish()
548    }
549}
550
551#[must_use = "If unused the read lock is immediatly released"]
552#[derive(Clone)]
553pub(crate) struct ReadGuard<T>(T);
554
555impl<T> Deref for ReadGuard<T>
556where
557    T: Deref,
558    <T as Deref>::Target: LazyData,
559{
560    type Target = <<T as Deref>::Target as LazyData>::Target;
561    #[inline(always)]
562    fn deref(&self) -> &Self::Target {
563        unsafe { &*(*self.0).get() }
564    }
565}
566
567impl<T> Debug for ReadGuard<T>
568where
569    T: Deref,
570    <T as Deref>::Target: LazyData,
571    <<T as Deref>::Target as LazyData>::Target: Debug,
572{
573    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
574        f.debug_tuple("ReadGuard").field(&*self).finish()
575    }
576}
577
578impl<T, U> From<WriteGuard<T>> for ReadGuard<U>
579where
580    U: From<T>,
581{
582    #[inline(always)]
583    fn from(v: WriteGuard<T>) -> Self {
584        Self(v.0.into())
585    }
586}
587
588impl<T> Phased for ReadGuard<T>
589where
590    T: Phased,
591{
592    #[inline(always)]
593    fn phase(this: &Self) -> Phase {
594        Phased::phase(&this.0)
595    }
596}
597
598#[cfg(any(feature = "parking_lot_core", debug_mode))]
599impl<T: LazyData> RefUnwindSafe for ReadGuard<T> where <T as LazyData>::Target: RefUnwindSafe {}
600
601#[cfg(any(feature = "parking_lot_core", debug_mode))]
602impl<T: LazyData> RefUnwindSafe for WriteGuard<T> where <T as LazyData>::Target: RefUnwindSafe {}
603
604/// A type that wrap a Sequentializer and a raw data, and that may
605/// initialize the data, at each access depending on the LazyPolicy
606/// provided as generic argument.
607pub(crate) struct GenericLockedLazy<T, F, M, S> {
608    seq: GenericLockedLazySeq<T, M>,
609    generator: F,
610    phantom: PhantomData<S>,
611    #[cfg(debug_mode)]
612    _info: Option<StaticInfo>,
613}
614
615impl<T, F, M, S> GenericLockedLazy<T, F, M, S> {
616    #[inline(always)]
617    /// const initialize the lazy, the inner data may be in an uninitialized state
618    ///
619    /// # Safety
620    ///
621    /// ## Constraint on T
622    ///
623    /// Should initialize the object when init is called and the method get should
624    /// return a pointer without UB if the object is not initialized
625    ///
626    /// ## Constraint on P
627    ///
628    /// The parameter M should be a lazy sequentializer that ensure that:
629    ///  1. When finalize is called, no other shared reference to the inner data exist
630    ///  2. The finalization is run only if the object was previously initialized
631    ///
632    /// ## Constraint on F
633    ///
634    /// The parameter F should be a Generator that ensured that the object
635    /// is accessble after a call to generate succeeds
636    ///
637    /// ## Constraint on S
638    ///
639    /// S should be a lazy policy that report correctly when the object
640    /// is accessbile, this in adequation with M and F.
641    pub const unsafe fn new(generator: F, sequentializer: M, value: T) -> Self {
642        Self {
643            seq: GenericLockedLazySeq {
644                value,
645                sequentializer,
646            },
647            generator,
648            phantom: PhantomData,
649            #[cfg(debug_mode)]
650            _info: None,
651        }
652    }
653    #[inline(always)]
654    /// const initialize the lazy, the inner data may be in an uninitialized state
655    ///
656    /// # Safety
657    ///
658    /// ## Constraint on T
659    ///
660    /// Should initialize the object when init is called and the method get should
661    /// return a pointer without UB if the object is not initialized
662    ///
663    /// ## Constraint on P
664    ///
665    /// The parameter M should be a lazy sequentializer that ensure that:
666    ///  1. When finalize is called, no other shared reference to the inner data exist
667    ///  2. The finalization is run only if the object was previously initialized
668    ///
669    /// ## Constraint on F
670    ///
671    /// The parameter F should be a Generator that ensured that the object
672    /// is accessble after a call to generate succeeds
673    ///
674    /// ## Constraint on S
675    ///
676    /// S should be a lazy policy that report correctly when the object
677    /// is accessbile, this in adequation with M and F.
678    pub const unsafe fn new_with_info(
679        generator: F,
680        sequentializer: M,
681        value: T,
682        _info: StaticInfo,
683    ) -> Self {
684        Self {
685            seq: GenericLockedLazySeq {
686                value,
687                sequentializer,
688            },
689            generator,
690            phantom: PhantomData,
691            #[cfg(debug_mode)]
692            _info: Some(_info),
693        }
694    }
695    #[inline(always)]
696    ///get access to the sequentializer
697    pub fn sequentializer(this: &Self) -> &M {
698        &this.seq.sequentializer
699    }
700}
701impl<'a, T, F, M, S> GenericLockedLazy<T, F, M, S>
702where
703    T: 'a + LazyData,
704    M: 'a,
705    M: LazySequentializer<'a, GenericLockedLazySeq<T, M>>,
706    F: 'a + Generator<T::Target>,
707    S: 'a + LazyPolicy,
708    M::ReadGuard: Phased,
709    M::WriteGuard: Phased,
710{
711    /// Get a mutable reference to the target
712    ///
713    /// # Safety
714    ///
715    /// Undefined behaviour if the referenced value has not been initialized
716    #[inline(always)]
717    pub unsafe fn get_mut_unchecked(&'a mut self) -> &'a mut T::Target {
718        &mut *self.seq.value.get()
719    }
720
721    /// Get a mutable reference to the target, returning an error if the
722    /// target is not in the correct phase.
723    #[inline(always)]
724    pub fn try_get_mut(&'a mut self) -> Result<&'a mut T::Target, AccessError> {
725        check_access::<*mut T::Target, S>(
726            self.seq.value.get(),
727            Phased::phase(&self.seq.sequentializer),
728        )
729        .map(|ptr| unsafe { &mut *ptr })
730    }
731
732    /// Get a reference to the target
733    ///
734    /// # Panics
735    ///
736    /// Panic if the target is not in the correct phase
737    #[inline(always)]
738    pub fn get_mut(&'a mut self) -> &'a mut T::Target {
739        self.try_get_mut().unwrap()
740    }
741    /// Attempt to get a read lock the LazyData object (not the target), returning None
742    /// if a unique lock is already held or in high contention cases.
743    ///
744    /// # Safety
745    ///
746    /// The obtained [ReadGuard] may reference an uninitialized target.
747    #[inline(always)]
748    pub unsafe fn fast_read_lock_unchecked(this: &'a Self) -> Option<ReadGuard<M::ReadGuard>> {
749        <M as Sequentializer<'a, GenericLockedLazySeq<T, M>>>::try_lock(
750            &this.seq,
751            |_| LockNature::Read,
752            M::INITIALIZED_HINT,
753        )
754        .map(|l| {
755            if let LockResult::Read(l) = l {
756                ReadGuard(l)
757            } else {
758                unreachable_unchecked()
759            }
760        })
761    }
762    /// Attempt to get a read lock the LazyData object (not the target), returning None
763    /// if a unique lock is already held or in high contention cases.
764    ///
765    /// If the lock succeeds and the object is not in an accessible phase, some error is returned
766    #[inline(always)]
767    pub fn fast_try_read_lock(
768        this: &'a Self,
769    ) -> Option<Result<ReadGuard<M::ReadGuard>, AccessError>> {
770        unsafe { Self::fast_read_lock_unchecked(this) }
771            .map(checked_access::<ReadGuard<M::ReadGuard>, S>)
772    }
773
774    /// Attempt to get a read lock the LazyData object (not the target), returning None
775    /// if a unique lock is already held or in high contention cases.
776    ///
777    /// # Panics
778    ///
779    /// Panics if the lock succeeds and the object is not in an accessible phase.
780    #[inline(always)]
781    pub fn fast_read_lock(this: &'a Self) -> Option<ReadGuard<M::ReadGuard>> {
782        Self::fast_try_read_lock(this).map(|r| r.unwrap())
783    }
784
785    /// Get a read lock the LazyData object (not the target)
786    ///
787    /// # Safety
788    ///
789    /// The obtained [ReadGuard] may reference an uninitialized target.
790    #[inline(always)]
791    pub unsafe fn read_lock_unchecked(this: &'a Self) -> ReadGuard<M::ReadGuard> {
792        if let LockResult::Read(l) = <M as Sequentializer<'a, GenericLockedLazySeq<T, M>>>::lock(
793            &this.seq,
794            |_| LockNature::Read,
795            M::INITIALIZED_HINT,
796        ) {
797            ReadGuard(l)
798        } else {
799            unreachable_unchecked()
800        }
801    }
802
803    /// Get a read lock the LazyData object (not the target)
804    ///
805    /// If the object is not in an accessible phase, some error is returned
806    #[inline(always)]
807    pub fn try_read_lock(this: &'a Self) -> Result<ReadGuard<M::ReadGuard>, AccessError> {
808        checked_access::<ReadGuard<M::ReadGuard>, S>(unsafe { Self::read_lock_unchecked(this) })
809    }
810
811    /// Get a read lock the LazyData object (not the target).
812    ///
813    /// # Panics
814    ///
815    /// Panics if the lock succeeds and the object is not in an accessible phase.
816    #[inline(always)]
817    pub fn read_lock(this: &'a Self) -> ReadGuard<M::ReadGuard> {
818        Self::try_read_lock(this).unwrap()
819    }
820
821    /// Attempt to get a write lock the LazyData object (not the target), returning None
822    /// if a lock is already held or in high contention cases.
823    ///
824    /// # Safety
825    ///
826    /// The obtained [ReadGuard] may reference an uninitialized target.
827    #[inline(always)]
828    pub unsafe fn fast_write_lock_unchecked(this: &'a Self) -> Option<WriteGuard<M::WriteGuard>> {
829        <M as Sequentializer<'a, GenericLockedLazySeq<T, M>>>::try_lock(
830            &this.seq,
831            |_| LockNature::Write,
832            M::INITIALIZED_HINT,
833        )
834        .map(|l| {
835            if let LockResult::Write(l) = l {
836                WriteGuard(l)
837            } else {
838                unreachable_unchecked()
839            }
840        })
841    }
842
843    /// Attempt to get a write lock the LazyData object (not the target), returning None
844    /// if a lock is already held or in high contention cases.
845    ///
846    /// If the lock succeeds and the object is not in an accessible phase, some error is returned
847    #[inline(always)]
848    pub fn fast_try_write_lock(
849        this: &'a Self,
850    ) -> Option<Result<WriteGuard<M::WriteGuard>, AccessError>> {
851        unsafe { Self::fast_write_lock_unchecked(this) }
852            .map(checked_access::<WriteGuard<M::WriteGuard>, S>)
853    }
854
855    /// Attempt to get a write lock the LazyData object (not the target), returning None
856    /// if a lock is already held or in high contention cases.
857    ///
858    /// # Panics
859    ///
860    /// Panics if the lock succeeds and the object is not in an accessible phase.
861    #[inline(always)]
862    pub fn fast_write_lock(this: &'a Self) -> Option<WriteGuard<M::WriteGuard>> {
863        Self::fast_try_write_lock(this).map(|r| r.unwrap())
864    }
865
866    /// Get a write lock the LazyData object (not the target)
867    ///
868    /// # Safety
869    ///
870    /// The obtained [ReadGuard] may reference an uninitialized target.
871    #[inline(always)]
872    pub unsafe fn write_lock_unchecked(this: &'a Self) -> WriteGuard<M::WriteGuard> {
873        if let LockResult::Write(l) = <M as Sequentializer<'a, GenericLockedLazySeq<T, M>>>::lock(
874            &this.seq,
875            |_| LockNature::Write,
876            M::INITIALIZED_HINT,
877        ) {
878            WriteGuard(l)
879        } else {
880            unreachable_unchecked()
881        }
882    }
883
884    /// Get a read lock the LazyData object (not the target)
885    ///
886    /// If the object is not in an accessible phase, an error is returned
887    #[inline(always)]
888    pub fn try_write_lock(this: &'a Self) -> Result<WriteGuard<M::WriteGuard>, AccessError> {
889        checked_access::<WriteGuard<M::WriteGuard>, S>(unsafe { Self::write_lock_unchecked(this) })
890    }
891
892    /// Get a write lock the LazyData object (not the target).
893    ///
894    /// # Panics
895    ///
896    /// Panics if the lock succeeds and the object is not in an accessible phase.
897    #[inline(always)]
898    pub fn write_lock(this: &'a Self) -> WriteGuard<M::WriteGuard> {
899        Self::try_write_lock(this).unwrap()
900    }
901
902    #[inline(always)]
903    /// Initialize if necessary then return a read lock
904    ///
905    /// # Safety
906    ///
907    /// Undefined behaviour if after initialization the return object is not in an accessible
908    /// state.
909    pub unsafe fn init_then_read_lock_unchecked(this: &'a Self) -> ReadGuard<M::ReadGuard> {
910        let r = may_debug(
911            || {
912                <M as LazySequentializer<'a, GenericLockedLazySeq<T, M>>>::init_then_read_guard(
913                    &this.seq,
914                    S::shall_init,
915                    |data: &T| {
916                        // SAFETY
917                        // This function is called only once within the init function
918                        // Only one thread can ever get this mutable access
919                        let d = Generator::generate(&this.generator);
920                        #[allow(unused_unsafe)]
921                        unsafe {
922                            data.init(d)
923                        };
924                    },
925                )
926            },
927            #[cfg(debug_mode)]
928            &this._info,
929        );
930        ReadGuard(r)
931    }
932
933    /// Initialize if necessary then return a read lock
934    ///
935    /// Returns an error if after initialization the return object is not in an accessible
936    /// state.
937    #[inline(always)]
938    pub fn init_then_try_read_lock(this: &'a Self) -> Result<ReadGuard<M::ReadGuard>, AccessError> {
939        post_init_checked_access::<ReadGuard<M::ReadGuard>, S>(unsafe {
940            Self::init_then_read_lock_unchecked(this)
941        })
942    }
943
944    /// Initialize if necessary then return a read lock
945    ///
946    /// # Panics
947    ///
948    /// Panics if after initialization the return object is not in an accessible
949    /// state.
950    #[inline(always)]
951    pub fn init_then_read_lock(this: &'a Self) -> ReadGuard<M::ReadGuard> {
952        Self::init_then_try_read_lock(this).unwrap()
953    }
954
955    /// If necessary attempt to get a write_lock initilialize the object then turn the write
956    /// lock into a read lock, otherwise attempt to get directly a read_lock. Attempt to take
957    /// a lock may fail because other locks are held or because of contention.
958    ///
959    /// # Safety
960    ///
961    /// If the target is not accessible this may cause undefined behaviour.
962    #[inline(always)]
963    pub unsafe fn fast_init_then_read_lock_unchecked(
964        this: &'a Self,
965    ) -> Option<ReadGuard<M::ReadGuard>> {
966        may_debug(
967            || {
968                <M as LazySequentializer<'a, GenericLockedLazySeq<T, M>>>::try_init_then_read_guard(
969                    &this.seq,
970                    S::shall_init,
971                    |data: &T| {
972                        // SAFETY
973                        // This function is called only once within the init function
974                        // Only one thread can ever get this mutable access
975                        let d = Generator::generate(&this.generator);
976                        #[allow(unused_unsafe)]
977                        unsafe {
978                            data.init(d)
979                        };
980                    },
981                )
982            },
983            #[cfg(debug_mode)]
984            &this._info,
985        )
986        .map(ReadGuard)
987    }
988
989    #[inline(always)]
990    /// If necessary attempt to get a write_lock initilialize the object then turn the write
991    /// lock into a read lock, otherwise attempt to get directly a read_lock. Attempt to take
992    /// a lock may fail because other locks are held or because of contention.
993    ///
994    /// If the target is not accessible some error is returned.
995    pub fn fast_init_then_try_read_lock(
996        this: &'a Self,
997    ) -> Option<Result<ReadGuard<M::ReadGuard>, AccessError>> {
998        unsafe { Self::fast_init_then_read_lock_unchecked(this) }
999            .map(post_init_checked_access::<ReadGuard<M::ReadGuard>, S>)
1000    }
1001
1002    #[inline(always)]
1003    /// If necessary attempt to get a write_lock initilialize the object then turn the write
1004    /// lock into a read lock, otherwise attempt to get directly a read_lock. Attempt to take
1005    /// a lock may fail because other locks are held or because of contention.
1006    ///
1007    /// # Panics
1008    ///
1009    /// If the target is not accessible some error is returned.
1010    pub fn fast_init_then_read_lock(this: &'a Self) -> Option<ReadGuard<M::ReadGuard>> {
1011        Self::fast_init_then_try_read_lock(this).map(|r| r.unwrap())
1012    }
1013
1014    #[inline(always)]
1015    /// Get a write locks, initialize the target if necessary then returns a readlock.
1016    ///
1017    /// # Safety
1018    ///
1019    /// If the target object is not accessible, this will cause undefined behaviour
1020    pub unsafe fn init_then_write_lock_unchecked(this: &'a Self) -> WriteGuard<M::WriteGuard> {
1021        let r = may_debug(
1022            || {
1023                <M as LazySequentializer<'a, GenericLockedLazySeq<T, M>>>::init_then_write_guard(
1024                    &this.seq,
1025                    S::shall_init,
1026                    |data: &T| {
1027                        // SAFETY
1028                        // This function is called only once within the init function
1029                        // Only one thread can ever get this mutable access
1030                        let d = Generator::generate(&this.generator);
1031                        #[allow(unused_unsafe)]
1032                        unsafe {
1033                            data.init(d)
1034                        };
1035                    },
1036                )
1037            },
1038            #[cfg(debug_mode)]
1039            &this._info,
1040        );
1041        WriteGuard(r)
1042    }
1043
1044    #[inline(always)]
1045    /// Get a write locks, initialize the target if necessary then returns the write lock.
1046    ///
1047    /// If the target object is not accessible an error is returned.
1048    pub fn init_then_try_write_lock(
1049        this: &'a Self,
1050    ) -> Result<WriteGuard<M::WriteGuard>, AccessError> {
1051        post_init_checked_access::<WriteGuard<M::WriteGuard>, S>(unsafe {
1052            Self::init_then_write_lock_unchecked(this)
1053        })
1054    }
1055    #[inline(always)]
1056    /// Get a write locks, initialize the target if necessary then returns a write lock.
1057    ///
1058    /// Panics if the target object is not accessible.
1059    #[inline(always)]
1060    pub fn init_then_write_lock(this: &'a Self) -> WriteGuard<M::WriteGuard> {
1061        Self::init_then_try_write_lock(this).unwrap()
1062    }
1063
1064    #[inline(always)]
1065    /// Attempt to get a write locks then initialize the target if necessary and returns the
1066    /// writelock.
1067    ///
1068    /// # Safety
1069    ///
1070    /// Undefined behavior if the target object is not accessible.
1071    pub unsafe fn fast_init_then_write_lock_unchecked(
1072        this: &'a Self,
1073    ) -> Option<WriteGuard<M::WriteGuard>> {
1074        may_debug(
1075            || {
1076                <M as LazySequentializer<'a, GenericLockedLazySeq<T, M>>>::try_init_then_write_guard(
1077                    &this.seq,
1078                    S::shall_init,
1079                    |data: &T| {
1080                        // SAFETY
1081                        // This function is called only once within the init function
1082                        // Only one thread can ever get this mutable access
1083                        let d = Generator::generate(&this.generator);
1084                        #[allow(unused_unsafe)]
1085                        unsafe { data.init(d) };
1086                    },
1087                )
1088            },
1089            #[cfg(debug_mode)]
1090            &this._info,
1091        )
1092        .map(WriteGuard)
1093    }
1094    /// Attempt to get a write locks then initialize the target if necessary and returns the
1095    /// writelock.
1096    ///
1097    /// Returns an error if the target object is not accessible.
1098    #[inline(always)]
1099    pub fn fast_init_then_try_write_lock(
1100        this: &'a Self,
1101    ) -> Option<Result<WriteGuard<M::WriteGuard>, AccessError>> {
1102        unsafe { Self::fast_init_then_write_lock_unchecked(this) }
1103            .map(post_init_checked_access::<WriteGuard<M::WriteGuard>, S>)
1104    }
1105    /// Attempt to get a write locks then initialize the target if necessary and returns the
1106    /// writelock.
1107    ///
1108    /// # Panics
1109    ///
1110    /// Panics if the target object is not accessible.
1111    #[inline(always)]
1112    pub fn fast_init_then_write_lock(this: &'a Self) -> Option<WriteGuard<M::WriteGuard>> {
1113        Self::fast_init_then_try_write_lock(this).map(|r| r.unwrap())
1114    }
1115}
1116
1117impl<T, F, M, S> GenericLockedLazy<T, F, M, S>
1118where
1119    M: UniqueLazySequentializer<GenericLockedLazySeq<T, M>>,
1120    T: LazyData,
1121    S: LazyPolicy,
1122    F: Generator<T::Target>,
1123{
1124    #[inline(always)]
1125    /// Attempt initialization then get a mutable reference to the target
1126    ///
1127    /// # Safety
1128    ///
1129    /// Undefined behaviour if the referenced value has not been initialized
1130    pub unsafe fn only_init_then_get_mut_unchecked(&mut self) -> &mut T::Target {
1131        self.only_init_unique();
1132        &mut *self.seq.value.get()
1133    }
1134    #[inline(always)]
1135    /// Attempt initialization then get a mutable reference to the target, returning an error if the
1136    /// target is not in the correct phase.
1137    pub fn only_init_then_try_get_mut(&mut self) -> Result<&mut T::Target, AccessError> {
1138        let phase = self.only_init_unique();
1139        check_access::<*mut T::Target, S>(self.seq.value.get(), phase)
1140            .map(|ptr| unsafe { &mut *ptr })
1141    }
1142    #[inline(always)]
1143    /// Attempt initialization then get a mutable reference to the target, returning an error if the
1144    /// target is not in the correct phase.
1145    pub fn only_init_then_get_mut(&mut self) -> &mut T::Target {
1146        Self::only_init_then_try_get_mut(self).unwrap()
1147    }
1148    #[inline(always)]
1149    /// Potentialy initialize the inner data, returning the
1150    /// phase reached at the end of the initialization attempt
1151    pub fn only_init_unique(&mut self) -> Phase {
1152        let generator = &self.generator;
1153        let seq = &mut self.seq;
1154        <M as UniqueLazySequentializer<GenericLockedLazySeq<T, M>>>::init_unique(
1155            seq,
1156            S::shall_init,
1157            |data: &mut T| {
1158                // SAFETY
1159                // This function is called only once within the init function
1160                // Only one thread can ever get this mutable access
1161                let d = Generator::generate(generator);
1162                unsafe { data.init_mut(d) };
1163            },
1164        )
1165    }
1166}
1167
1168//SAFETY: data and sequentialize are two fields of Self.
1169unsafe impl<T: LazyData, M> Sequential for GenericLockedLazySeq<T, M> {
1170    type Data = T;
1171    type Sequentializer = M;
1172    #[inline(always)]
1173    fn sequentializer(this: &Self) -> &Self::Sequentializer {
1174        &this.sequentializer
1175    }
1176    #[inline(always)]
1177    fn sequentializer_data_mut(this: &mut Self) -> (&mut Self::Sequentializer, &mut Self::Data) {
1178        (&mut this.sequentializer, &mut this.value)
1179    }
1180    #[inline(always)]
1181    fn data(this: &Self) -> &Self::Data {
1182        &this.value
1183    }
1184}
1185impl<F, T, M, S> Deref for GenericLockedLazy<T, F, M, S> {
1186    type Target = T;
1187    #[inline(always)]
1188    ///get a pointer to the raw data
1189    fn deref(&self) -> &T {
1190        &self.seq.value
1191    }
1192}
1193impl<T, M> Deref for GenericLockedLazySeq<T, M> {
1194    type Target = T;
1195    #[inline(always)]
1196    ///get a pointer to the raw data
1197    fn deref(&self) -> &T {
1198        &self.value
1199    }
1200}
1201
1202impl<F, T, M: Phased, S> Phased for GenericLockedLazy<T, F, M, S> {
1203    #[inline(always)]
1204    fn phase(this: &Self) -> Phase {
1205        Phased::phase(&this.seq.sequentializer)
1206    }
1207}
1208impl<F, T, M: Phased, S> Phased for GenericLazy<T, F, M, S> {
1209    #[inline(always)]
1210    fn phase(this: &Self) -> Phase {
1211        Phased::phase(&this.seq.sequentializer)
1212    }
1213}
1214
1215#[inline(always)]
1216fn may_debug<R, F: FnOnce() -> R>(f: F, #[cfg(debug_mode)] info: &Option<StaticInfo>) -> R {
1217    #[cfg(not(debug_mode))]
1218    {
1219        f()
1220    }
1221    #[cfg(debug_mode)]
1222    {
1223        match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f())) {
1224            Ok(r) => r,
1225            Err(x) => {
1226                if x.is::<CyclicPanic>() {
1227                    match info {
1228                        Some(info) => panic!("Circular initialization of {:#?}", info),
1229                        None => panic!("Circular lazy initialization detected"),
1230                    }
1231                } else {
1232                    std::panic::resume_unwind(x)
1233                }
1234            }
1235        }
1236    }
1237}
1238
1239#[inline(always)]
1240fn check_access<T, S: LazyPolicy>(l: T, phase: Phase) -> Result<T, AccessError> {
1241    if S::is_accessible(phase) {
1242        Ok(l)
1243    } else {
1244        Err(AccessError { phase })
1245    }
1246}
1247
1248#[inline(always)]
1249fn checked_access<T: Phased, S: LazyPolicy>(l: T) -> Result<T, AccessError> {
1250    let phase = Phased::phase(&l);
1251    check_access::<T, S>(l, phase)
1252}
1253#[inline(always)]
1254fn post_init_check_access<T, S: LazyPolicy>(l: T, phase: Phase) -> Result<T, AccessError> {
1255    if S::post_init_is_accessible(phase) {
1256        Ok(l)
1257    } else {
1258        Err(AccessError { phase })
1259    }
1260}
1261
1262#[inline(always)]
1263fn post_init_checked_access<T: Phased, S: LazyPolicy>(l: T) -> Result<T, AccessError> {
1264    let phase = Phased::phase(&l);
1265    post_init_check_access::<T, S>(l, phase)
1266}