intuicio_data/
lifetime.rs

1use std::{
2    ops::{Deref, DerefMut},
3    sync::{
4        atomic::{AtomicBool, AtomicUsize, Ordering},
5        Arc, Weak,
6    },
7};
8
9#[derive(Default)]
10struct LifetimeStateInner {
11    locked: AtomicBool,
12    readers: AtomicUsize,
13    writer: AtomicUsize,
14    read_access: AtomicUsize,
15    write_access: AtomicBool,
16}
17
18#[derive(Default, Clone)]
19pub struct LifetimeState {
20    inner: Arc<LifetimeStateInner>,
21}
22
23impl LifetimeState {
24    pub fn can_read(&self) -> bool {
25        self.inner.writer.load(Ordering::Acquire) == 0
26    }
27
28    pub fn can_write(&self, id: usize) -> bool {
29        self.inner.writer.load(Ordering::Acquire) == id
30            && self.inner.readers.load(Ordering::Acquire) == 0
31    }
32
33    pub fn writer_depth(&self) -> usize {
34        self.inner.writer.load(Ordering::Acquire)
35    }
36
37    pub fn is_read_accessible(&self) -> bool {
38        !self.inner.write_access.load(Ordering::Acquire)
39    }
40
41    pub fn is_write_accessible(&self) -> bool {
42        !self.inner.write_access.load(Ordering::Acquire)
43            && self.inner.read_access.load(Ordering::Acquire) == 0
44    }
45
46    pub fn is_in_use(&self) -> bool {
47        self.inner.read_access.load(Ordering::Acquire) > 0
48            || self.inner.write_access.load(Ordering::Acquire)
49    }
50
51    pub fn is_locked(&self) -> bool {
52        self.inner.locked.load(Ordering::Acquire)
53    }
54
55    pub fn try_lock(&self) -> Option<LifetimeStateAccess> {
56        if !self.inner.locked.load(Ordering::Acquire) {
57            self.inner.locked.store(true, Ordering::Release);
58            Some(LifetimeStateAccess {
59                state: self,
60                unlock: true,
61            })
62        } else {
63            None
64        }
65    }
66
67    pub fn lock(&self) -> LifetimeStateAccess {
68        while self.inner.locked.load(Ordering::Acquire) {
69            std::hint::spin_loop();
70        }
71        self.inner.locked.store(true, Ordering::Release);
72        LifetimeStateAccess {
73            state: self,
74            unlock: true,
75        }
76    }
77
78    /// # Safety
79    pub unsafe fn lock_unchecked(&self) -> LifetimeStateAccess {
80        LifetimeStateAccess {
81            state: self,
82            unlock: true,
83        }
84    }
85
86    pub fn downgrade(&self) -> LifetimeWeakState {
87        LifetimeWeakState {
88            inner: Arc::downgrade(&self.inner),
89        }
90    }
91}
92
93#[derive(Clone)]
94pub struct LifetimeWeakState {
95    inner: Weak<LifetimeStateInner>,
96}
97
98impl LifetimeWeakState {
99    pub fn upgrade(&self) -> Option<LifetimeState> {
100        Some(LifetimeState {
101            inner: self.inner.upgrade()?,
102        })
103    }
104
105    pub fn is_owned_by(&self, state: &LifetimeState) -> bool {
106        Arc::downgrade(&state.inner).ptr_eq(&self.inner)
107    }
108}
109
110pub struct LifetimeStateAccess<'a> {
111    state: &'a LifetimeState,
112    unlock: bool,
113}
114
115impl Drop for LifetimeStateAccess<'_> {
116    fn drop(&mut self) {
117        if self.unlock {
118            self.state.inner.locked.store(false, Ordering::Release);
119        }
120    }
121}
122
123impl LifetimeStateAccess<'_> {
124    pub fn state(&self) -> &LifetimeState {
125        self.state
126    }
127
128    pub fn unlock(&mut self, value: bool) {
129        self.unlock = value;
130    }
131
132    pub fn acquire_reader(&mut self) {
133        let v = self.state.inner.readers.load(Ordering::Acquire) + 1;
134        self.state.inner.readers.store(v, Ordering::Release);
135    }
136
137    pub fn release_reader(&mut self) {
138        let v = self
139            .state
140            .inner
141            .readers
142            .load(Ordering::Acquire)
143            .saturating_sub(1);
144        self.state.inner.readers.store(v, Ordering::Release);
145    }
146
147    #[must_use]
148    pub fn acquire_writer(&mut self) -> usize {
149        let v = self.state.inner.writer.load(Ordering::Acquire) + 1;
150        self.state.inner.writer.store(v, Ordering::Release);
151        v
152    }
153
154    pub fn release_writer(&mut self, id: usize) {
155        let v = self.state.inner.writer.load(Ordering::Acquire);
156        if id <= v {
157            self.state
158                .inner
159                .writer
160                .store(id.saturating_sub(1), Ordering::Release);
161        }
162    }
163
164    pub fn acquire_read_access(&mut self) {
165        let v = self.state.inner.read_access.load(Ordering::Acquire) + 1;
166        self.state.inner.read_access.store(v, Ordering::Release);
167    }
168
169    pub fn release_read_access(&mut self) {
170        let v = self
171            .state
172            .inner
173            .read_access
174            .load(Ordering::Acquire)
175            .saturating_sub(1);
176        self.state.inner.read_access.store(v, Ordering::Release);
177    }
178
179    pub fn acquire_write_access(&mut self) {
180        self.state.inner.write_access.store(true, Ordering::Release);
181    }
182
183    pub fn release_write_access(&mut self) {
184        self.state
185            .inner
186            .write_access
187            .store(false, Ordering::Release);
188    }
189}
190
191#[derive(Default)]
192pub struct Lifetime(LifetimeState);
193
194impl Lifetime {
195    pub fn state(&self) -> &LifetimeState {
196        &self.0
197    }
198
199    pub fn borrow(&self) -> Option<LifetimeRef> {
200        self.0
201            .try_lock()
202            .filter(|access| access.state.can_read())
203            .map(|mut access| {
204                access.acquire_reader();
205                LifetimeRef(self.0.downgrade())
206            })
207    }
208
209    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
210        self.0
211            .try_lock()
212            .filter(|access| access.state.can_write(0))
213            .map(|mut access| {
214                let id = access.acquire_writer();
215                LifetimeRefMut(self.0.downgrade(), id)
216            })
217    }
218
219    pub fn lazy(&self) -> LifetimeLazy {
220        LifetimeLazy(self.0.downgrade())
221    }
222
223    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
224        self.0
225            .try_lock()
226            .filter(|access| access.state.is_read_accessible())
227            .map(|mut access| {
228                access.unlock = false;
229                access.acquire_read_access();
230                ValueReadAccess {
231                    lifetime: self.0.clone(),
232                    data,
233                }
234            })
235    }
236
237    /// # Safety
238    pub unsafe fn read_ptr<T: ?Sized>(&self, data: *const T) -> Option<ValueReadAccess<T>> {
239        self.0
240            .try_lock()
241            .filter(|access| access.state.is_read_accessible())
242            .and_then(|mut access| {
243                access.unlock = false;
244                access.acquire_read_access();
245                Some(ValueReadAccess {
246                    lifetime: self.0.clone(),
247                    data: data.as_ref()?,
248                })
249            })
250    }
251
252    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
253        self.0
254            .try_lock()
255            .filter(|access| access.state.is_write_accessible())
256            .map(|mut access| {
257                access.unlock = false;
258                access.acquire_write_access();
259                ValueWriteAccess {
260                    lifetime: self.0.clone(),
261                    data,
262                }
263            })
264    }
265
266    /// # Safety
267    pub unsafe fn write_ptr<T: ?Sized>(&self, data: *mut T) -> Option<ValueWriteAccess<T>> {
268        self.0
269            .try_lock()
270            .filter(|access| access.state.is_write_accessible())
271            .and_then(|mut access| {
272                access.unlock = false;
273                access.acquire_write_access();
274                Some(ValueWriteAccess {
275                    lifetime: self.0.clone(),
276                    data: data.as_mut()?,
277                })
278            })
279    }
280
281    pub fn read_lock(&self) -> ReadLock {
282        let mut access = self.0.lock();
283        while !access.state.is_read_accessible() {
284            std::hint::spin_loop();
285        }
286        access.unlock = false;
287        access.acquire_read_access();
288        ReadLock {
289            lifetime: self.0.clone(),
290        }
291    }
292
293    pub fn write_lock(&self) -> WriteLock {
294        let mut access = self.0.lock();
295        while !access.state.is_write_accessible() {
296            std::hint::spin_loop();
297        }
298        access.unlock = false;
299        access.acquire_write_access();
300        WriteLock {
301            lifetime: self.0.clone(),
302        }
303    }
304}
305
306pub struct LifetimeRef(LifetimeWeakState);
307
308impl Drop for LifetimeRef {
309    fn drop(&mut self) {
310        if let Some(owner) = self.0.upgrade() {
311            if let Some(mut access) = owner.try_lock() {
312                access.release_reader();
313            }
314        }
315    }
316}
317
318impl LifetimeRef {
319    pub fn state(&self) -> &LifetimeWeakState {
320        &self.0
321    }
322
323    pub fn exists(&self) -> bool {
324        self.0.upgrade().is_some()
325    }
326
327    pub fn can_read(&self) -> bool {
328        self.0
329            .upgrade()
330            .map(|state| state.can_read())
331            .unwrap_or(false)
332    }
333
334    pub fn is_read_accessible(&self) -> bool {
335        self.0
336            .upgrade()
337            .map(|state| state.is_read_accessible())
338            .unwrap_or(false)
339    }
340
341    pub fn is_in_use(&self) -> bool {
342        self.0
343            .upgrade()
344            .map(|state| state.is_in_use())
345            .unwrap_or(false)
346    }
347
348    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
349        self.0.is_owned_by(&other.0)
350    }
351
352    pub fn borrow(&self) -> Option<LifetimeRef> {
353        self.0
354            .upgrade()?
355            .try_lock()
356            .filter(|access| access.state.can_read())
357            .map(|mut access| {
358                access.acquire_reader();
359                LifetimeRef(self.0.clone())
360            })
361    }
362
363    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
364        let state = self.0.upgrade()?;
365        let mut access = state.try_lock()?;
366        if access.state.is_read_accessible() {
367            access.unlock = false;
368            access.acquire_read_access();
369            drop(access);
370            Some(ValueReadAccess {
371                lifetime: state,
372                data,
373            })
374        } else {
375            None
376        }
377    }
378
379    /// # Safety
380    pub unsafe fn read_ptr<T: ?Sized>(&self, data: *const T) -> Option<ValueReadAccess<T>> {
381        let state = self.0.upgrade()?;
382        let mut access = state.try_lock()?;
383        if access.state.is_read_accessible() {
384            access.unlock = false;
385            access.acquire_read_access();
386            drop(access);
387            Some(ValueReadAccess {
388                lifetime: state,
389                data: data.as_ref()?,
390            })
391        } else {
392            None
393        }
394    }
395
396    pub fn read_lock(&self) -> Option<ReadLock> {
397        let state = self.0.upgrade()?;
398        let mut access = state.lock();
399        while !access.state.is_read_accessible() {
400            std::hint::spin_loop();
401        }
402        access.unlock = false;
403        access.acquire_read_access();
404        Some(ReadLock {
405            lifetime: state.clone(),
406        })
407    }
408
409    pub fn consume<T: ?Sized>(self, data: &T) -> Result<ValueReadAccess<T>, Self> {
410        let state = match self.0.upgrade() {
411            Some(state) => state,
412            None => return Err(self),
413        };
414        let mut access = match state.try_lock() {
415            Some(access) => access,
416            None => return Err(self),
417        };
418        if access.state.is_read_accessible() {
419            access.unlock = false;
420            access.acquire_read_access();
421            drop(access);
422            Ok(ValueReadAccess {
423                lifetime: state,
424                data,
425            })
426        } else {
427            Err(self)
428        }
429    }
430}
431
432pub struct LifetimeRefMut(LifetimeWeakState, usize);
433
434impl Drop for LifetimeRefMut {
435    fn drop(&mut self) {
436        if let Some(state) = self.0.upgrade() {
437            if let Some(mut access) = state.try_lock() {
438                access.release_writer(self.1);
439            }
440        }
441    }
442}
443
444impl LifetimeRefMut {
445    pub fn state(&self) -> &LifetimeWeakState {
446        &self.0
447    }
448
449    pub fn depth(&self) -> usize {
450        self.1
451    }
452
453    pub fn exists(&self) -> bool {
454        self.0.upgrade().is_some()
455    }
456
457    pub fn can_read(&self) -> bool {
458        self.0
459            .upgrade()
460            .map(|state| state.can_read())
461            .unwrap_or(false)
462    }
463
464    pub fn can_write(&self) -> bool {
465        self.0
466            .upgrade()
467            .map(|state| state.can_write(self.1))
468            .unwrap_or(false)
469    }
470
471    pub fn is_read_accessible(&self) -> bool {
472        self.0
473            .upgrade()
474            .map(|state| state.is_read_accessible())
475            .unwrap_or(false)
476    }
477
478    pub fn is_write_accessible(&self) -> bool {
479        self.0
480            .upgrade()
481            .map(|state| state.is_write_accessible())
482            .unwrap_or(false)
483    }
484
485    pub fn is_in_use(&self) -> bool {
486        self.0
487            .upgrade()
488            .map(|state| state.is_in_use())
489            .unwrap_or(false)
490    }
491
492    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
493        self.0.is_owned_by(&other.0)
494    }
495
496    pub fn borrow(&self) -> Option<LifetimeRef> {
497        self.0
498            .upgrade()?
499            .try_lock()
500            .filter(|access| access.state.can_read())
501            .map(|mut access| {
502                access.acquire_reader();
503                LifetimeRef(self.0.clone())
504            })
505    }
506
507    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
508        self.0
509            .upgrade()?
510            .try_lock()
511            .filter(|access| access.state.can_write(self.1))
512            .map(|mut access| {
513                let id = access.acquire_writer();
514                LifetimeRefMut(self.0.clone(), id)
515            })
516    }
517
518    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
519        let state = self.0.upgrade()?;
520        let mut access = state.try_lock()?;
521        if access.state.is_read_accessible() {
522            access.unlock = false;
523            access.acquire_read_access();
524            drop(access);
525            Some(ValueReadAccess {
526                lifetime: state,
527                data,
528            })
529        } else {
530            None
531        }
532    }
533
534    /// # Safety
535    pub unsafe fn read_ptr<T: ?Sized>(&self, data: *const T) -> Option<ValueReadAccess<T>> {
536        let state = self.0.upgrade()?;
537        let mut access = state.try_lock()?;
538        if access.state.is_read_accessible() {
539            access.unlock = false;
540            access.acquire_read_access();
541            drop(access);
542            Some(ValueReadAccess {
543                lifetime: state,
544                data: data.as_ref()?,
545            })
546        } else {
547            None
548        }
549    }
550
551    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
552        let state = self.0.upgrade()?;
553        let mut access = state.try_lock()?;
554        if access.state.is_write_accessible() {
555            access.unlock = false;
556            access.acquire_write_access();
557            drop(access);
558            Some(ValueWriteAccess {
559                lifetime: state,
560                data,
561            })
562        } else {
563            None
564        }
565    }
566
567    /// # Safety
568    pub unsafe fn write_ptr<T: ?Sized>(&self, data: *mut T) -> Option<ValueWriteAccess<T>> {
569        let state = self.0.upgrade()?;
570        let mut access = state.try_lock()?;
571        if access.state.is_write_accessible() {
572            access.unlock = false;
573            access.acquire_write_access();
574            drop(access);
575            Some(ValueWriteAccess {
576                lifetime: state,
577                data: data.as_mut()?,
578            })
579        } else {
580            None
581        }
582    }
583
584    pub fn read_lock(&self) -> Option<ReadLock> {
585        let state = self.0.upgrade()?;
586        let mut access = state.lock();
587        while !access.state.is_read_accessible() {
588            std::hint::spin_loop();
589        }
590        access.unlock = false;
591        access.acquire_read_access();
592        Some(ReadLock {
593            lifetime: state.clone(),
594        })
595    }
596
597    pub fn write_lock(&self) -> Option<WriteLock> {
598        let state = self.0.upgrade()?;
599        let mut access = state.lock();
600        while !access.state.is_write_accessible() {
601            std::hint::spin_loop();
602        }
603        access.unlock = false;
604        access.acquire_write_access();
605        Some(WriteLock {
606            lifetime: state.clone(),
607        })
608    }
609
610    pub fn consume<T: ?Sized>(self, data: &mut T) -> Result<ValueWriteAccess<T>, Self> {
611        let state = match self.0.upgrade() {
612            Some(state) => state,
613            None => return Err(self),
614        };
615        let mut access = match state.try_lock() {
616            Some(access) => access,
617            None => return Err(self),
618        };
619        if access.state.is_write_accessible() {
620            access.unlock = false;
621            access.acquire_write_access();
622            drop(access);
623            Ok(ValueWriteAccess {
624                lifetime: state,
625                data,
626            })
627        } else {
628            Err(self)
629        }
630    }
631}
632
633#[derive(Clone)]
634pub struct LifetimeLazy(LifetimeWeakState);
635
636impl LifetimeLazy {
637    pub fn state(&self) -> &LifetimeWeakState {
638        &self.0
639    }
640
641    pub fn exists(&self) -> bool {
642        self.0.upgrade().is_some()
643    }
644
645    pub fn is_read_accessible(&self) -> bool {
646        self.0
647            .upgrade()
648            .map(|state| state.is_read_accessible())
649            .unwrap_or(false)
650    }
651
652    pub fn is_write_accessible(&self) -> bool {
653        self.0
654            .upgrade()
655            .map(|state| state.is_write_accessible())
656            .unwrap_or(false)
657    }
658
659    pub fn is_in_use(&self) -> bool {
660        self.0
661            .upgrade()
662            .map(|state| state.is_in_use())
663            .unwrap_or(false)
664    }
665
666    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
667        self.0.is_owned_by(&other.0)
668    }
669
670    pub fn borrow(&self) -> Option<LifetimeRef> {
671        self.0
672            .upgrade()?
673            .try_lock()
674            .filter(|access| access.state.can_read())
675            .map(|mut access| {
676                access.acquire_reader();
677                LifetimeRef(self.0.clone())
678            })
679    }
680
681    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
682        self.0
683            .upgrade()?
684            .try_lock()
685            .filter(|access| access.state.can_write(0))
686            .map(|mut access| {
687                let id = access.acquire_writer();
688                LifetimeRefMut(self.0.clone(), id)
689            })
690    }
691
692    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
693        let state = self.0.upgrade()?;
694        let mut access = state.try_lock()?;
695        if access.state.is_read_accessible() {
696            access.unlock = false;
697            access.acquire_read_access();
698            drop(access);
699            Some(ValueReadAccess {
700                lifetime: state,
701                data,
702            })
703        } else {
704            None
705        }
706    }
707
708    /// # Safety
709    pub unsafe fn read_ptr<T: ?Sized>(&self, data: *const T) -> Option<ValueReadAccess<T>> {
710        let state = self.0.upgrade()?;
711        let mut access = state.try_lock()?;
712        if access.state.is_read_accessible() {
713            access.unlock = false;
714            access.acquire_read_access();
715            drop(access);
716            Some(ValueReadAccess {
717                lifetime: state,
718                data: data.as_ref()?,
719            })
720        } else {
721            None
722        }
723    }
724
725    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
726        let state = self.0.upgrade()?;
727        let mut access = state.try_lock()?;
728        if access.state.is_write_accessible() {
729            access.unlock = false;
730            access.acquire_write_access();
731            drop(access);
732            Some(ValueWriteAccess {
733                lifetime: state,
734                data,
735            })
736        } else {
737            None
738        }
739    }
740
741    /// # Safety
742    pub unsafe fn write_ptr<T: ?Sized>(&self, data: *mut T) -> Option<ValueWriteAccess<T>> {
743        let state = self.0.upgrade()?;
744        let mut access = state.try_lock()?;
745        if access.state.is_write_accessible() {
746            access.unlock = false;
747            access.acquire_write_access();
748            drop(access);
749            Some(ValueWriteAccess {
750                lifetime: state,
751                data: data.as_mut()?,
752            })
753        } else {
754            None
755        }
756    }
757
758    pub fn consume<T: ?Sized>(self, data: &mut T) -> Result<ValueWriteAccess<T>, Self> {
759        let state = match self.0.upgrade() {
760            Some(state) => state,
761            None => return Err(self),
762        };
763        let mut access = match state.try_lock() {
764            Some(access) => access,
765            None => return Err(self),
766        };
767        if access.state.is_write_accessible() {
768            access.unlock = false;
769            access.acquire_write_access();
770            drop(access);
771            Ok(ValueWriteAccess {
772                lifetime: state,
773                data,
774            })
775        } else {
776            Err(self)
777        }
778    }
779}
780
781pub struct ValueReadAccess<'a, T: 'a + ?Sized> {
782    lifetime: LifetimeState,
783    data: &'a T,
784}
785
786impl<T: ?Sized> Drop for ValueReadAccess<'_, T> {
787    fn drop(&mut self) {
788        unsafe { self.lifetime.lock_unchecked().release_read_access() };
789    }
790}
791
792impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
793    /// # Safety
794    pub unsafe fn new_raw(data: &'a T, lifetime: LifetimeState) -> Self {
795        Self { lifetime, data }
796    }
797}
798
799impl<T: ?Sized> Deref for ValueReadAccess<'_, T> {
800    type Target = T;
801
802    fn deref(&self) -> &Self::Target {
803        self.data
804    }
805}
806
807impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
808    pub fn remap<U>(
809        self,
810        f: impl FnOnce(&T) -> Option<&U>,
811    ) -> Result<ValueReadAccess<'a, U>, Self> {
812        if let Some(data) = f(self.data) {
813            Ok(ValueReadAccess {
814                lifetime: self.lifetime.clone(),
815                data,
816            })
817        } else {
818            Err(self)
819        }
820    }
821}
822
823pub struct ValueWriteAccess<'a, T: 'a + ?Sized> {
824    lifetime: LifetimeState,
825    data: &'a mut T,
826}
827
828impl<T: ?Sized> Drop for ValueWriteAccess<'_, T> {
829    fn drop(&mut self) {
830        unsafe { self.lifetime.lock_unchecked().release_write_access() };
831    }
832}
833
834impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
835    /// # Safety
836    pub unsafe fn new_raw(data: &'a mut T, lifetime: LifetimeState) -> Self {
837        Self { lifetime, data }
838    }
839}
840
841impl<T: ?Sized> Deref for ValueWriteAccess<'_, T> {
842    type Target = T;
843
844    fn deref(&self) -> &Self::Target {
845        self.data
846    }
847}
848
849impl<T: ?Sized> DerefMut for ValueWriteAccess<'_, T> {
850    fn deref_mut(&mut self) -> &mut Self::Target {
851        self.data
852    }
853}
854
855impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
856    pub fn remap<U>(
857        self,
858        f: impl FnOnce(&mut T) -> Option<&mut U>,
859    ) -> Result<ValueWriteAccess<'a, U>, Self> {
860        if let Some(data) = f(unsafe { std::mem::transmute::<&mut T, &'a mut T>(&mut *self.data) })
861        {
862            Ok(ValueWriteAccess {
863                lifetime: self.lifetime.clone(),
864                data,
865            })
866        } else {
867            Err(self)
868        }
869    }
870}
871
872pub struct ReadLock {
873    lifetime: LifetimeState,
874}
875
876impl Drop for ReadLock {
877    fn drop(&mut self) {
878        unsafe { self.lifetime.lock_unchecked().release_read_access() };
879    }
880}
881
882impl ReadLock {
883    /// # Safety
884    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
885        Self { lifetime }
886    }
887
888    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
889        let result = f();
890        drop(self);
891        result
892    }
893}
894
895pub struct WriteLock {
896    lifetime: LifetimeState,
897}
898
899impl Drop for WriteLock {
900    fn drop(&mut self) {
901        unsafe { self.lifetime.lock_unchecked().release_write_access() };
902    }
903}
904
905impl WriteLock {
906    /// # Safety
907    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
908        Self { lifetime }
909    }
910
911    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
912        let result = f();
913        drop(self);
914        result
915    }
916}
917
918#[cfg(test)]
919mod tests {
920    use super::*;
921    use std::thread::*;
922
923    fn is_async<T: Send + Sync + ?Sized>() {
924        println!("{} is async!", std::any::type_name::<T>());
925    }
926
927    #[test]
928    fn test_lifetimes() {
929        is_async::<Lifetime>();
930        is_async::<LifetimeRef>();
931        is_async::<LifetimeRefMut>();
932        is_async::<LifetimeLazy>();
933
934        let mut value = 0usize;
935        let lifetime_ref = {
936            let lifetime = Lifetime::default();
937            assert!(lifetime.state().can_read());
938            assert!(lifetime.state().can_write(0));
939            assert!(lifetime.state().is_read_accessible());
940            assert!(lifetime.state().is_write_accessible());
941            let lifetime_lazy = lifetime.lazy();
942            assert!(lifetime_lazy.read(&42).is_some());
943            assert!(lifetime_lazy.write(&mut 42).is_some());
944            {
945                let access = lifetime.read(&value).unwrap();
946                assert_eq!(*access, value);
947            }
948            {
949                let mut access = lifetime.write(&mut value).unwrap();
950                *access = 42;
951                assert_eq!(*access, 42);
952            }
953            {
954                let lifetime_ref = lifetime.borrow().unwrap();
955                assert!(lifetime.state().can_read());
956                assert!(!lifetime.state().can_write(0));
957                assert!(lifetime_ref.exists());
958                assert!(lifetime_ref.is_owned_by(&lifetime));
959                assert!(lifetime.borrow().is_some());
960                assert!(lifetime.borrow_mut().is_none());
961                assert!(lifetime_lazy.read(&42).is_some());
962                assert!(lifetime_lazy.write(&mut 42).is_some());
963                {
964                    let access = lifetime_ref.read(&value).unwrap();
965                    assert_eq!(*access, 42);
966                    assert!(lifetime_lazy.read(&42).is_none());
967                    assert!(lifetime_lazy.write(&mut 42).is_none());
968                }
969                let lifetime_ref2 = lifetime_ref.borrow().unwrap();
970                {
971                    let access = lifetime_ref2.read(&value).unwrap();
972                    assert_eq!(*access, 42);
973                    assert!(lifetime_lazy.read(&42).is_none());
974                    assert!(lifetime_lazy.write(&mut 42).is_none());
975                }
976            }
977            {
978                let lifetime_ref_mut = lifetime.borrow_mut().unwrap();
979                assert_eq!(lifetime.state().writer_depth(), 1);
980                assert!(!lifetime.state().can_read());
981                assert!(!lifetime.state().can_write(0));
982                assert!(lifetime_ref_mut.exists());
983                assert!(lifetime_ref_mut.is_owned_by(&lifetime));
984                assert!(lifetime.borrow().is_none());
985                assert!(lifetime.borrow_mut().is_none());
986                assert!(lifetime_lazy.read(&42).is_some());
987                assert!(lifetime_lazy.write(&mut 42).is_some());
988                {
989                    let mut access = lifetime_ref_mut.write(&mut value).unwrap();
990                    *access = 7;
991                    assert_eq!(*access, 7);
992                    assert!(lifetime_lazy.read(&42).is_none());
993                    assert!(lifetime_lazy.write(&mut 42).is_none());
994                }
995                let lifetime_ref_mut2 = lifetime_ref_mut.borrow_mut().unwrap();
996                assert!(lifetime_lazy.read(&42).is_some());
997                assert!(lifetime_lazy.write(&mut 42).is_some());
998                {
999                    assert_eq!(lifetime.state().writer_depth(), 2);
1000                    assert!(lifetime.borrow().is_none());
1001                    assert!(lifetime_ref_mut.borrow().is_none());
1002                    assert!(lifetime.borrow_mut().is_none());
1003                    assert!(lifetime_ref_mut.borrow_mut().is_none());
1004                    let mut access = lifetime_ref_mut2.write(&mut value).unwrap();
1005                    *access = 42;
1006                    assert_eq!(*access, 42);
1007                    assert!(lifetime.read(&42).is_none());
1008                    assert!(lifetime_ref_mut.read(&42).is_none());
1009                    assert!(lifetime.write(&mut 42).is_none());
1010                    assert!(lifetime_ref_mut.write(&mut 42).is_none());
1011                    assert!(lifetime_lazy.read(&42).is_none());
1012                    assert!(lifetime_lazy.write(&mut 42).is_none());
1013                    assert!(lifetime_lazy.read(&42).is_none());
1014                    assert!(lifetime_lazy.write(&mut 42).is_none());
1015                }
1016            }
1017            assert_eq!(lifetime.state().writer_depth(), 0);
1018            lifetime.borrow().unwrap()
1019        };
1020        assert!(!lifetime_ref.exists());
1021        assert_eq!(value, 42);
1022    }
1023
1024    #[test]
1025    fn test_lifetimes_multithread() {
1026        let lifetime = Lifetime::default();
1027        let lifetime_ref = lifetime.borrow().unwrap();
1028        assert!(lifetime_ref.exists());
1029        assert!(lifetime_ref.is_owned_by(&lifetime));
1030        drop(lifetime);
1031        assert!(!lifetime_ref.exists());
1032        let lifetime = Lifetime::default();
1033        let lifetime = spawn(move || {
1034            let value_ref = lifetime.borrow().unwrap();
1035            assert!(value_ref.exists());
1036            assert!(value_ref.is_owned_by(&lifetime));
1037            lifetime
1038        })
1039        .join()
1040        .unwrap();
1041        assert!(!lifetime_ref.exists());
1042        assert!(!lifetime_ref.is_owned_by(&lifetime));
1043    }
1044}