Skip to main content

intuicio_data/
lifetime.rs

1//! Runtime borrow checking for values Rust cannot track statically.
2//!
3//! Script values live in type-erased storage, so the compiler cannot prove
4//! that a script does not alias them. A [`Lifetime`] is a small piece of
5//! shared state that answers that question at runtime instead: it hands out
6//! handles, and refuses to hand out a conflicting one.
7//!
8//! # Two independent axes
9//!
10//! A lifetime tracks borrows and accesses separately.
11//!
12//! **Borrows** are long lived claims, the runtime analogue of `&` and `&mut`:
13//!
14//! - [`Lifetime::borrow`] gives a [`LifetimeRef`]. Many can coexist, and they
15//!   block mutable borrows.
16//! - [`Lifetime::borrow_mut`] gives a [`LifetimeRefMut`]. It needs no readers
17//!   and no other writer. Writers nest: an existing [`LifetimeRefMut`] can
18//!   reborrow itself mutably, which raises the writer depth.
19//! - [`Lifetime::lazy`] gives a [`LifetimeLazy`], which claims nothing and
20//!   only checks conditions when it is actually used.
21//!
22//! **Accesses** are short lived guards over the data itself, taken from any of
23//! the handles above:
24//!
25//! - `read` returns a [`ValueReadAccess`]. Many can coexist.
26//! - `write` returns a [`ValueWriteAccess`]. It excludes every other access.
27//! - [`ReadLock`] and [`WriteLock`] are the same guards without the data,
28//!   for holding a claim across code that does not touch the value.
29//!
30//! Every method has a non-blocking form returning [`None`], a spinning form,
31//! and an `_async` form that yields to the executor while it waits.
32//!
33//! # Dangling handles
34//!
35//! Handles hold a weak reference plus a tag, so they detect an owner that was
36//! dropped or reset with [`Lifetime::invalidate`], and report it by returning
37//! [`None`] rather than by dangling.
38//!
39//! ```
40//! # use intuicio_data::lifetime::Lifetime;
41//! let mut value = 0usize;
42//! let lifetime = Lifetime::default();
43//! *lifetime.write(&mut value).unwrap() = 42;
44//! let borrow = lifetime.borrow().unwrap();
45//! // a reader is out, so nobody can borrow mutably
46//! assert!(lifetime.borrow_mut().is_none());
47//! assert_eq!(*borrow.read(&value).unwrap(), 42);
48//!
49//! // read guards share, so several can be out at the same time
50//! let first = lifetime.read(&value).unwrap();
51//! let second = lifetime.read(&value).unwrap();
52//! assert_eq!((*first, *second), (42, 42));
53//! ```
54use std::{
55    future::poll_fn,
56    ops::{Deref, DerefMut},
57    sync::{
58        Arc, Weak,
59        atomic::{AtomicBool, AtomicUsize, Ordering},
60    },
61    task::Poll,
62};
63
64/// Counters shared by one [`Lifetime`] and all handles derived from it.
65///
66/// `locked` is a spin lock guarding the rest, so that a check and the update
67/// that follows it cannot be interleaved with another thread.
68#[derive(Default)]
69struct LifetimeStateInner {
70    locked: AtomicBool,
71    readers: AtomicUsize,
72    writer: AtomicUsize,
73    read_access: AtomicUsize,
74    write_access: AtomicBool,
75    tag: AtomicUsize,
76}
77
78/// Cloneable strong handle to the counters behind a [`Lifetime`].
79///
80/// Mostly an implementation detail of this module. Keeping one alive keeps
81/// the counters alive, but it does not itself claim a borrow or an access.
82#[derive(Default, Clone)]
83pub struct LifetimeState {
84    inner: Arc<LifetimeStateInner>,
85}
86
87impl LifetimeState {
88    /// Returns `true` when no mutable borrow is out.
89    pub fn can_read(&self) -> bool {
90        self.inner.writer.load(Ordering::Acquire) == 0
91    }
92
93    /// Returns `true` when there are no readers and `id` is the current writer
94    /// depth.
95    ///
96    /// Pass `0` to ask for a top level mutable borrow, or the depth of an
97    /// existing [`LifetimeRefMut`] to ask for a nested reborrow.
98    pub fn can_write(&self, id: usize) -> bool {
99        self.inner.writer.load(Ordering::Acquire) == id
100            && self.inner.readers.load(Ordering::Acquire) == 0
101    }
102
103    /// Returns how many [`LifetimeRef`] handles are out.
104    pub fn readers_count(&self) -> usize {
105        self.inner.readers.load(Ordering::Acquire)
106    }
107
108    /// Returns how deeply mutable borrows are nested, `0` when none is out.
109    pub fn writer_depth(&self) -> usize {
110        self.inner.writer.load(Ordering::Acquire)
111    }
112
113    /// Returns `true` when no write access guard is live.
114    pub fn is_read_accessible(&self) -> bool {
115        !self.inner.write_access.load(Ordering::Acquire)
116    }
117
118    /// Returns `true` when no access guard of any kind is live.
119    pub fn is_write_accessible(&self) -> bool {
120        !self.inner.write_access.load(Ordering::Acquire)
121            && self.inner.read_access.load(Ordering::Acquire) == 0
122    }
123
124    /// Returns `true` while any access guard is live.
125    pub fn is_in_use(&self) -> bool {
126        self.inner.read_access.load(Ordering::Acquire) > 0
127            || self.inner.write_access.load(Ordering::Acquire)
128    }
129
130    /// Returns `true` while another thread holds the internal spin lock.
131    pub fn is_locked(&self) -> bool {
132        self.inner.locked.load(Ordering::Acquire)
133    }
134
135    /// Takes the internal spin lock, or returns [`None`] when it is taken.
136    pub fn try_lock(&'_ self) -> Option<LifetimeStateAccess<'_>> {
137        if self
138            .inner
139            .locked
140            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
141            .is_ok()
142        {
143            Some(LifetimeStateAccess {
144                state: self,
145                unlock: true,
146            })
147        } else {
148            None
149        }
150    }
151
152    /// Takes the internal spin lock, spinning until it is free.
153    pub fn lock(&'_ self) -> LifetimeStateAccess<'_> {
154        while self
155            .inner
156            .locked
157            .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
158            .is_err()
159        {
160            std::hint::spin_loop();
161        }
162        LifetimeStateAccess {
163            state: self,
164            unlock: true,
165        }
166    }
167
168    /// Builds a lock guard without taking the lock.
169    ///
170    /// # Safety
171    ///
172    /// No other thread must update the counters while this guard lives. If one
173    /// does, the read-modify-write pairs in [`LifetimeStateAccess`] can lose an
174    /// update.
175    pub unsafe fn lock_unchecked(&'_ self) -> LifetimeStateAccess<'_> {
176        LifetimeStateAccess {
177            state: self,
178            unlock: true,
179        }
180    }
181
182    /// Stamps the address of the owning [`Lifetime`] as the current tag.
183    ///
184    /// # Safety
185    ///
186    /// `tag` must be the [`Lifetime`] that owns this state. Passing another one
187    /// makes stale handles look valid again.
188    pub unsafe fn update_tag(&self, tag: &Lifetime) {
189        let tag = tag as *const Lifetime as usize;
190        self.inner.tag.store(tag, Ordering::Release);
191    }
192
193    /// Clears the tag, so every handle taken so far stops upgrading.
194    ///
195    /// # Safety
196    ///
197    /// Callers holding handles will see them go dead. Use through
198    /// [`Lifetime::invalidate`] rather than directly.
199    pub unsafe fn invalidate_tag(&self) {
200        self.inner.tag.store(0, Ordering::Release);
201    }
202
203    /// Returns the current tag, or `0` when the state was invalidated.
204    pub fn tag(&self) -> usize {
205        self.inner.tag.load(Ordering::Acquire)
206    }
207
208    /// Takes a weak handle that remembers the current tag.
209    pub fn downgrade(&self) -> LifetimeWeakState {
210        LifetimeWeakState {
211            inner: Arc::downgrade(&self.inner),
212            tag: self.inner.tag.load(Ordering::Acquire),
213        }
214    }
215}
216
217/// Weak handle to a [`LifetimeState`], paired with the tag it was taken at.
218///
219/// [`LifetimeWeakState::upgrade`] fails once the owner is gone or the tag
220/// changed, which is how [`LifetimeRef`], [`LifetimeRefMut`] and
221/// [`LifetimeLazy`] notice they went stale.
222#[derive(Clone)]
223pub struct LifetimeWeakState {
224    inner: Weak<LifetimeStateInner>,
225    tag: usize,
226}
227
228impl LifetimeWeakState {
229    /// Upgrades without checking the tag, so it succeeds even for a lifetime
230    /// that was invalidated and reused.
231    ///
232    /// # Safety
233    ///
234    /// The counters are always valid to touch, but the value the lifetime used
235    /// to guard may be a different one by now. Only use this to release
236    /// counters that this handle itself acquired.
237    pub unsafe fn upgrade_unchecked(&self) -> Option<LifetimeState> {
238        Some(LifetimeState {
239            inner: self.inner.upgrade()?,
240        })
241    }
242
243    /// Upgrades to a strong handle, or returns [`None`] when the owner is gone
244    /// or was invalidated.
245    pub fn upgrade(&self) -> Option<LifetimeState> {
246        let inner = self.inner.upgrade()?;
247        (inner.tag.load(Ordering::Acquire) == self.tag).then_some(LifetimeState { inner })
248    }
249
250    /// Returns `true` when this handle points at `state`.
251    pub fn is_owned_by(&self, state: &LifetimeState) -> bool {
252        Arc::downgrade(&state.inner).ptr_eq(&self.inner)
253    }
254}
255
256/// Guard over the internal spin lock of a [`LifetimeState`], through which
257/// the borrow and access counters are updated.
258///
259/// Releases the lock on drop. Hold it only long enough to check a condition
260/// and update the counters: while it is taken, every other handle to the same
261/// lifetime is refused or spinning.
262pub struct LifetimeStateAccess<'a> {
263    state: &'a LifetimeState,
264    unlock: bool,
265}
266
267impl Drop for LifetimeStateAccess<'_> {
268    fn drop(&mut self) {
269        if self.unlock {
270            self.state.inner.locked.store(false, Ordering::Release);
271        }
272    }
273}
274
275impl LifetimeStateAccess<'_> {
276    /// Returns the locked state.
277    pub fn state(&self) -> &LifetimeState {
278        self.state
279    }
280
281    /// Chooses whether dropping this guard releases the spin lock.
282    ///
283    /// With `false` the lock stays taken until something releases it through
284    /// [`LifetimeState::lock_unchecked`]. A held lock blocks every other handle
285    /// to the same lifetime.
286    pub fn unlock(&mut self, value: bool) {
287        self.unlock = value;
288    }
289
290    /// Counts one more shared borrow.
291    pub fn acquire_reader(&mut self) {
292        let v = self.state.inner.readers.load(Ordering::Acquire) + 1;
293        self.state.inner.readers.store(v, Ordering::Release);
294    }
295
296    /// Counts one shared borrow less, saturating at zero.
297    pub fn release_reader(&mut self) {
298        let v = self
299            .state
300            .inner
301            .readers
302            .load(Ordering::Acquire)
303            .saturating_sub(1);
304        self.state.inner.readers.store(v, Ordering::Release);
305    }
306
307    /// Counts one more nested mutable borrow and returns its new depth.
308    ///
309    /// The depth has to be given back to [`LifetimeStateAccess::release_writer`].
310    #[must_use]
311    pub fn acquire_writer(&mut self) -> usize {
312        let v = self.state.inner.writer.load(Ordering::Acquire) + 1;
313        self.state.inner.writer.store(v, Ordering::Release);
314        v
315    }
316
317    /// Drops the mutable borrow at depth `id`, along with anything nested
318    /// inside it. Does nothing when `id` is deeper than the current depth.
319    pub fn release_writer(&mut self, id: usize) {
320        let v = self.state.inner.writer.load(Ordering::Acquire);
321        if id <= v {
322            self.state
323                .inner
324                .writer
325                .store(id.saturating_sub(1), Ordering::Release);
326        }
327    }
328
329    /// Counts one more live read guard.
330    pub fn acquire_read_access(&mut self) {
331        let v = self.state.inner.read_access.load(Ordering::Acquire) + 1;
332        self.state.inner.read_access.store(v, Ordering::Release);
333    }
334
335    /// Counts one live read guard less, saturating at zero.
336    pub fn release_read_access(&mut self) {
337        let v = self
338            .state
339            .inner
340            .read_access
341            .load(Ordering::Acquire)
342            .saturating_sub(1);
343        self.state.inner.read_access.store(v, Ordering::Release);
344    }
345
346    /// Marks a write guard as live, excluding every other access.
347    pub fn acquire_write_access(&mut self) {
348        self.state.inner.write_access.store(true, Ordering::Release);
349    }
350
351    /// Marks the write guard as gone.
352    pub fn release_write_access(&mut self) {
353        self.state
354            .inner
355            .write_access
356            .store(false, Ordering::Release);
357    }
358}
359
360/// Owner of a runtime borrow state, kept next to the value it describes.
361///
362/// Dropping it, or calling [`Lifetime::invalidate`], kills every handle
363/// taken from it. See the [module docs](self) for the borrow and access
364/// model.
365#[derive(Default)]
366pub struct Lifetime(LifetimeState);
367
368impl Lifetime {
369    /// Kills every handle taken so far and starts over with fresh counters.
370    ///
371    /// Call this when the value behind the lifetime is replaced, so that old
372    /// handles cannot reach the new value.
373    pub fn invalidate(&mut self) {
374        unsafe { self.0.invalidate_tag() };
375        self.0 = Default::default();
376    }
377
378    /// Returns the shared state, refreshing the tag first.
379    pub fn state(&self) -> &LifetimeState {
380        unsafe { self.0.update_tag(self) };
381        &self.0
382    }
383
384    /// Re-stamps the tag with the current address of this lifetime.
385    ///
386    /// Needed after the lifetime was moved in memory, so handles taken before
387    /// the move keep upgrading.
388    pub fn update_tag(&self) {
389        unsafe { self.0.update_tag(self) };
390    }
391
392    /// Returns the current tag.
393    pub fn tag(&self) -> usize {
394        unsafe { self.0.update_tag(self) };
395        self.0.tag()
396    }
397
398    /// Takes a shared borrow, or returns [`None`] when a mutable borrow is out.
399    pub fn borrow(&self) -> Option<LifetimeRef> {
400        unsafe { self.0.update_tag(self) };
401        self.0
402            .try_lock()
403            .filter(|access| access.state.can_read())
404            .map(|mut access| {
405                access.acquire_reader();
406                LifetimeRef(self.0.downgrade())
407            })
408    }
409
410    /// [`Lifetime::borrow`], awaiting until it succeeds.
411    pub async fn borrow_async(&self) -> LifetimeRef {
412        loop {
413            if let Some(lifetime_ref) = self.borrow() {
414                return lifetime_ref;
415            }
416            poll_fn(|cx| {
417                cx.waker().wake_by_ref();
418                Poll::<LifetimeRef>::Pending
419            })
420            .await;
421        }
422    }
423
424    /// Takes a mutable borrow, or returns [`None`] when any other borrow is out.
425    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
426        unsafe { self.0.update_tag(self) };
427        self.0
428            .try_lock()
429            .filter(|access| access.state.can_write(0))
430            .map(|mut access| {
431                let id = access.acquire_writer();
432                LifetimeRefMut(self.0.downgrade(), id)
433            })
434    }
435
436    /// [`Lifetime::borrow_mut`], awaiting until it succeeds.
437    pub async fn borrow_mut_async(&self) -> LifetimeRefMut {
438        loop {
439            if let Some(lifetime_ref_mut) = self.borrow_mut() {
440                return lifetime_ref_mut;
441            }
442            poll_fn(|cx| {
443                cx.waker().wake_by_ref();
444                Poll::<LifetimeRefMut>::Pending
445            })
446            .await;
447        }
448    }
449
450    /// Takes a handle that claims no borrow and is checked only when used.
451    pub fn lazy(&self) -> LifetimeLazy {
452        unsafe { self.0.update_tag(self) };
453        LifetimeLazy(self.0.downgrade())
454    }
455
456    /// Guards `data` for reading, or returns [`None`] while a write guard is
457    /// live.
458    ///
459    /// The caller has to pass the data that this lifetime guards. The lifetime
460    /// only tracks the permission.
461    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
462        unsafe { self.0.update_tag(self) };
463        self.0
464            .try_lock()
465            .filter(|access| access.state.is_read_accessible())
466            .map(|mut access| {
467                access.acquire_read_access();
468                ValueReadAccess {
469                    lifetime: self.0.clone(),
470                    data,
471                }
472            })
473    }
474
475    /// [`Lifetime::read`], awaiting until it succeeds.
476    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
477        unsafe { self.read_ptr_async(data as *const T).await }
478    }
479
480    /// [`Lifetime::read`] over a raw pointer.
481    ///
482    /// # Safety
483    ///
484    /// `data` must stay valid and aligned for as long as the returned guard
485    /// lives. A null pointer yields [`None`].
486    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
487        let data = unsafe { data.as_ref() }?;
488        unsafe { self.0.update_tag(self) };
489        self.0
490            .try_lock()
491            .filter(|access| access.state.is_read_accessible())
492            .map(|mut access| {
493                access.acquire_read_access();
494                ValueReadAccess {
495                    lifetime: self.0.clone(),
496                    data,
497                }
498            })
499    }
500
501    /// [`Lifetime::read_ptr`], awaiting until it succeeds.
502    ///
503    /// # Safety
504    ///
505    /// Same as [`Lifetime::read_ptr`], and `data` must also stay valid across
506    /// every await point.
507    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
508        &'a self,
509        data: *const T,
510    ) -> ValueReadAccess<'a, T> {
511        loop {
512            if let Some(access) = unsafe { self.read_ptr(data) } {
513                return access;
514            }
515            poll_fn(|cx| {
516                cx.waker().wake_by_ref();
517                Poll::<ValueReadAccess<'a, T>>::Pending
518            })
519            .await;
520        }
521    }
522
523    /// Guards `data` for writing, or returns [`None`] while any other access
524    /// guard is live.
525    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
526        unsafe { self.0.update_tag(self) };
527        self.0
528            .try_lock()
529            .filter(|access| access.state.is_write_accessible())
530            .map(|mut access| {
531                access.acquire_write_access();
532                ValueWriteAccess {
533                    lifetime: self.0.clone(),
534                    data,
535                }
536            })
537    }
538
539    /// [`Lifetime::write`], awaiting until it succeeds.
540    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
541        unsafe { self.write_ptr_async(data as *mut T).await }
542    }
543
544    /// [`Lifetime::write`] over a raw pointer.
545    ///
546    /// # Safety
547    ///
548    /// `data` must stay valid, aligned and unaliased for as long as the
549    /// returned guard lives. A null pointer yields [`None`].
550    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
551        let data = unsafe { data.as_mut() }?;
552        unsafe { self.0.update_tag(self) };
553        self.0
554            .try_lock()
555            .filter(|access| access.state.is_write_accessible())
556            .map(|mut access| {
557                access.acquire_write_access();
558                ValueWriteAccess {
559                    lifetime: self.0.clone(),
560                    data,
561                }
562            })
563    }
564
565    /// [`Lifetime::write_ptr`], awaiting until it succeeds.
566    ///
567    /// # Safety
568    ///
569    /// Same as [`Lifetime::write_ptr`], and `data` must also stay valid across
570    /// every await point.
571    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
572        &'a self,
573        data: *mut T,
574    ) -> ValueWriteAccess<'a, T> {
575        loop {
576            if let Some(access) = unsafe { self.write_ptr(data) } {
577                return access;
578            }
579            poll_fn(|cx| {
580                cx.waker().wake_by_ref();
581                Poll::<ValueWriteAccess<'a, T>>::Pending
582            })
583            .await;
584        }
585    }
586
587    /// Claims read access without holding any data, or returns [`None`] when a
588    /// write guard is live.
589    pub fn try_read_lock(&self) -> Option<ReadLock> {
590        unsafe { self.0.update_tag(self) };
591        let mut access = self.0.lock();
592        if !access.state.is_read_accessible() {
593            return None;
594        }
595        access.acquire_read_access();
596        Some(ReadLock {
597            lifetime: self.0.clone(),
598        })
599    }
600
601    /// [`Lifetime::try_read_lock`], spinning until it succeeds.
602    pub fn read_lock(&self) -> ReadLock {
603        unsafe { self.0.update_tag(self) };
604        let mut access = self.0.lock();
605        while !access.state.is_read_accessible() {
606            std::hint::spin_loop();
607        }
608        access.acquire_read_access();
609        ReadLock {
610            lifetime: self.0.clone(),
611        }
612    }
613
614    /// [`Lifetime::try_read_lock`], awaiting until it succeeds.
615    pub async fn read_lock_async(&self) -> ReadLock {
616        loop {
617            unsafe { self.0.update_tag(self) };
618            let mut access = self.0.lock();
619            if access.state.is_read_accessible() {
620                access.acquire_read_access();
621                return ReadLock {
622                    lifetime: self.0.clone(),
623                };
624            }
625            poll_fn(|cx| {
626                cx.waker().wake_by_ref();
627                Poll::<ReadLock>::Pending
628            })
629            .await;
630        }
631    }
632
633    /// Claims write access without holding any data, or returns [`None`] when
634    /// any access guard is live.
635    pub fn try_write_lock(&self) -> Option<WriteLock> {
636        unsafe { self.0.update_tag(self) };
637        let mut access = self.0.lock();
638        if !access.state.is_write_accessible() {
639            return None;
640        }
641        access.acquire_write_access();
642        Some(WriteLock {
643            lifetime: self.0.clone(),
644        })
645    }
646
647    /// [`Lifetime::try_write_lock`], spinning until it succeeds.
648    pub fn write_lock(&self) -> WriteLock {
649        unsafe { self.0.update_tag(self) };
650        let mut access = self.0.lock();
651        while !access.state.is_write_accessible() {
652            std::hint::spin_loop();
653        }
654        access.acquire_write_access();
655        WriteLock {
656            lifetime: self.0.clone(),
657        }
658    }
659
660    /// [`Lifetime::try_write_lock`], awaiting until it succeeds.
661    pub async fn write_lock_async(&self) -> WriteLock {
662        loop {
663            unsafe { self.0.update_tag(self) };
664            let mut access = self.0.lock();
665            if access.state.is_write_accessible() {
666                access.acquire_write_access();
667                return WriteLock {
668                    lifetime: self.0.clone(),
669                };
670            }
671            poll_fn(|cx| {
672                cx.waker().wake_by_ref();
673                Poll::<WriteLock>::Pending
674            })
675            .await;
676        }
677    }
678
679    /// Awaits until reading would be allowed, without claiming anything.
680    pub async fn wait_for_read_access(&self) {
681        loop {
682            if self.state().is_read_accessible() {
683                return;
684            }
685            poll_fn(|cx| {
686                cx.waker().wake_by_ref();
687                Poll::<()>::Pending
688            })
689            .await;
690        }
691    }
692
693    /// Awaits until writing would be allowed, without claiming anything.
694    pub async fn wait_for_write_access(&self) {
695        loop {
696            if self.state().is_write_accessible() {
697                return;
698            }
699            poll_fn(|cx| {
700                cx.waker().wake_by_ref();
701                Poll::<()>::Pending
702            })
703            .await;
704        }
705    }
706}
707
708/// Shared borrow of a [`Lifetime`], the runtime analogue of `&T`.
709///
710/// Many can coexist and they keep mutable borrows out. Releases its claim
711/// on drop.
712pub struct LifetimeRef(LifetimeWeakState);
713
714impl Drop for LifetimeRef {
715    fn drop(&mut self) {
716        if let Some(owner) = unsafe { self.0.upgrade_unchecked() }
717            && let Some(mut access) = owner.try_lock()
718        {
719            access.release_reader();
720        }
721    }
722}
723
724impl LifetimeRef {
725    /// Returns the weak state this borrow points at.
726    pub fn state(&self) -> &LifetimeWeakState {
727        &self.0
728    }
729
730    /// Returns the tag the owner had when this borrow was taken.
731    pub fn tag(&self) -> usize {
732        self.0.tag
733    }
734
735    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
736    pub fn exists(&self) -> bool {
737        self.0.upgrade().is_some()
738    }
739
740    /// Returns `true` when another shared borrow could be taken.
741    pub fn can_read(&self) -> bool {
742        self.0
743            .upgrade()
744            .map(|state| state.can_read())
745            .unwrap_or(false)
746    }
747
748    /// Returns `true` when no write guard is live.
749    pub fn is_read_accessible(&self) -> bool {
750        self.0
751            .upgrade()
752            .map(|state| state.is_read_accessible())
753            .unwrap_or(false)
754    }
755
756    /// Returns `true` while any access guard is live.
757    pub fn is_in_use(&self) -> bool {
758        self.0
759            .upgrade()
760            .map(|state| state.is_in_use())
761            .unwrap_or(false)
762    }
763
764    /// Returns `true` when this borrow came from `other`.
765    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
766        self.0.is_owned_by(&other.0)
767    }
768
769    /// Takes another shared borrow of the same lifetime.
770    pub fn borrow(&self) -> Option<LifetimeRef> {
771        self.0
772            .upgrade()?
773            .try_lock()
774            .filter(|access| access.state.can_read())
775            .map(|mut access| {
776                access.acquire_reader();
777                LifetimeRef(self.0.clone())
778            })
779    }
780
781    /// [`LifetimeRef::borrow`], awaiting until it succeeds.
782    pub async fn borrow_async(&self) -> LifetimeRef {
783        loop {
784            if let Some(lifetime_ref) = self.borrow() {
785                return lifetime_ref;
786            }
787            poll_fn(|cx| {
788                cx.waker().wake_by_ref();
789                Poll::<LifetimeRef>::Pending
790            })
791            .await;
792        }
793    }
794
795    /// Takes a lazy handle to the same lifetime.
796    pub fn lazy(&self) -> LifetimeLazy {
797        LifetimeLazy(self.0.clone())
798    }
799
800    /// Guards `data` for reading, or returns [`None`] while a write guard is
801    /// live or the owner is gone.
802    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
803        let state = self.0.upgrade()?;
804        let mut access = state.try_lock()?;
805        if access.state.is_read_accessible() {
806            access.acquire_read_access();
807            drop(access);
808            Some(ValueReadAccess {
809                lifetime: state,
810                data,
811            })
812        } else {
813            None
814        }
815    }
816
817    /// [`LifetimeRef::read`], awaiting until it succeeds.
818    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
819        loop {
820            if let Some(access) = self.read(data) {
821                return access;
822            }
823            poll_fn(|cx| {
824                cx.waker().wake_by_ref();
825                Poll::<ValueReadAccess<'a, T>>::Pending
826            })
827            .await;
828        }
829    }
830
831    /// [`LifetimeRef::read`] over a raw pointer.
832    ///
833    /// # Safety
834    ///
835    /// `data` must stay valid and aligned for as long as the returned guard
836    /// lives. A null pointer yields [`None`].
837    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
838        let data = unsafe { data.as_ref() }?;
839        let state = self.0.upgrade()?;
840        let mut access = state.try_lock()?;
841        if access.state.is_read_accessible() {
842            access.acquire_read_access();
843            drop(access);
844            Some(ValueReadAccess {
845                lifetime: state,
846                data,
847            })
848        } else {
849            None
850        }
851    }
852
853    /// [`LifetimeRef::read_ptr`], awaiting until it succeeds.
854    ///
855    /// # Safety
856    ///
857    /// Same as [`LifetimeRef::read_ptr`], and `data` must also stay valid
858    /// across every await point.
859    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
860        &'a self,
861        data: *const T,
862    ) -> ValueReadAccess<'a, T> {
863        loop {
864            if let Some(access) = unsafe { self.read_ptr(data) } {
865                return access;
866            }
867            poll_fn(|cx| {
868                cx.waker().wake_by_ref();
869                Poll::<ValueReadAccess<'a, T>>::Pending
870            })
871            .await;
872        }
873    }
874
875    /// Claims read access without holding any data.
876    pub fn try_read_lock(&self) -> Option<ReadLock> {
877        let state = self.0.upgrade()?;
878        let mut access = state.lock();
879        if !access.state.is_read_accessible() {
880            return None;
881        }
882        access.acquire_read_access();
883        Some(ReadLock {
884            lifetime: state.clone(),
885        })
886    }
887
888    /// [`LifetimeRef::try_read_lock`], spinning until it succeeds. Returns
889    /// [`None`] when the owner is gone.
890    pub fn read_lock(&self) -> Option<ReadLock> {
891        let state = self.0.upgrade()?;
892        let mut access = state.lock();
893        while !access.state.is_read_accessible() {
894            std::hint::spin_loop();
895        }
896        access.acquire_read_access();
897        Some(ReadLock {
898            lifetime: state.clone(),
899        })
900    }
901
902    /// [`LifetimeRef::read_lock`], awaiting until it succeeds.
903    pub async fn read_lock_async(&self) -> ReadLock {
904        loop {
905            if let Some(lock) = self.read_lock() {
906                return lock;
907            }
908            poll_fn(|cx| {
909                cx.waker().wake_by_ref();
910                Poll::<ReadLock>::Pending
911            })
912            .await;
913        }
914    }
915
916    /// Turns this borrow into a read guard over `data` that lives as long as
917    /// the borrow would have.
918    ///
919    /// Gives the borrow back unchanged when a write guard is live.
920    pub fn consume<T: ?Sized>(self, data: &'_ T) -> Result<ValueReadAccess<'_, T>, Self> {
921        let state = match self.0.upgrade() {
922            Some(state) => state,
923            None => return Err(self),
924        };
925        let mut access = match state.try_lock() {
926            Some(access) => access,
927            None => return Err(self),
928        };
929        if access.state.is_read_accessible() {
930            access.acquire_read_access();
931            drop(access);
932            Ok(ValueReadAccess {
933                lifetime: state,
934                data,
935            })
936        } else {
937            Err(self)
938        }
939    }
940
941    /// Awaits until reading would be allowed, or the owner is gone.
942    pub async fn wait_for_read_access(&self) {
943        loop {
944            let Some(state) = self.0.upgrade() else {
945                return;
946            };
947            if state.is_read_accessible() {
948                return;
949            }
950            poll_fn(|cx| {
951                cx.waker().wake_by_ref();
952                Poll::<()>::Pending
953            })
954            .await;
955        }
956    }
957
958    /// Awaits until writing would be allowed, or the owner is gone.
959    pub async fn wait_for_write_access(&self) {
960        loop {
961            let Some(state) = self.0.upgrade() else {
962                return;
963            };
964            if state.is_write_accessible() {
965                return;
966            }
967            poll_fn(|cx| {
968                cx.waker().wake_by_ref();
969                Poll::<()>::Pending
970            })
971            .await;
972        }
973    }
974}
975
976/// Mutable borrow of a [`Lifetime`], the runtime analogue of `&mut T`.
977///
978/// Excludes every other top level borrow, but can reborrow itself through
979/// [`LifetimeRefMut::borrow_mut`], which nests one level deeper. Releases
980/// its level, and everything nested under it, on drop.
981pub struct LifetimeRefMut(LifetimeWeakState, usize);
982
983impl Drop for LifetimeRefMut {
984    fn drop(&mut self) {
985        if let Some(state) = unsafe { self.0.upgrade_unchecked() }
986            && let Some(mut access) = state.try_lock()
987        {
988            access.release_writer(self.1);
989        }
990    }
991}
992
993impl LifetimeRefMut {
994    /// Returns the weak state this borrow points at.
995    pub fn state(&self) -> &LifetimeWeakState {
996        &self.0
997    }
998
999    /// Returns the tag the owner had when this borrow was taken.
1000    pub fn tag(&self) -> usize {
1001        self.0.tag
1002    }
1003
1004    /// Returns how deeply this mutable borrow is nested, starting at `1`.
1005    pub fn depth(&self) -> usize {
1006        self.1
1007    }
1008
1009    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
1010    pub fn exists(&self) -> bool {
1011        self.0.upgrade().is_some()
1012    }
1013
1014    /// Returns `true` when a shared borrow could be taken.
1015    pub fn can_read(&self) -> bool {
1016        self.0
1017            .upgrade()
1018            .map(|state| state.can_read())
1019            .unwrap_or(false)
1020    }
1021
1022    /// Returns `true` when this borrow could be reborrowed mutably.
1023    pub fn can_write(&self) -> bool {
1024        self.0
1025            .upgrade()
1026            .map(|state| state.can_write(self.1))
1027            .unwrap_or(false)
1028    }
1029
1030    /// Returns `true` when no write guard is live.
1031    pub fn is_read_accessible(&self) -> bool {
1032        self.0
1033            .upgrade()
1034            .map(|state| state.is_read_accessible())
1035            .unwrap_or(false)
1036    }
1037
1038    /// Returns `true` when no access guard of any kind is live.
1039    pub fn is_write_accessible(&self) -> bool {
1040        self.0
1041            .upgrade()
1042            .map(|state| state.is_write_accessible())
1043            .unwrap_or(false)
1044    }
1045
1046    /// Returns `true` while any access guard is live.
1047    pub fn is_in_use(&self) -> bool {
1048        self.0
1049            .upgrade()
1050            .map(|state| state.is_in_use())
1051            .unwrap_or(false)
1052    }
1053
1054    /// Returns `true` when this borrow came from `other`.
1055    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
1056        self.0.is_owned_by(&other.0)
1057    }
1058
1059    /// Takes a shared borrow, which only succeeds once this mutable borrow is
1060    /// not the innermost one.
1061    pub fn borrow(&self) -> Option<LifetimeRef> {
1062        self.0
1063            .upgrade()?
1064            .try_lock()
1065            .filter(|access| access.state.can_read())
1066            .map(|mut access| {
1067                access.acquire_reader();
1068                LifetimeRef(self.0.clone())
1069            })
1070    }
1071
1072    /// [`LifetimeRefMut::borrow`], awaiting until it succeeds.
1073    pub async fn borrow_async(&self) -> LifetimeRef {
1074        loop {
1075            if let Some(lifetime_ref) = self.borrow() {
1076                return lifetime_ref;
1077            }
1078            poll_fn(|cx| {
1079                cx.waker().wake_by_ref();
1080                Poll::<LifetimeRef>::Pending
1081            })
1082            .await;
1083        }
1084    }
1085
1086    /// Reborrows mutably one level deeper, or returns [`None`] when this is not
1087    /// the innermost mutable borrow.
1088    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
1089        self.0
1090            .upgrade()?
1091            .try_lock()
1092            .filter(|access| access.state.can_write(self.1))
1093            .map(|mut access| {
1094                let id = access.acquire_writer();
1095                LifetimeRefMut(self.0.clone(), id)
1096            })
1097    }
1098
1099    /// [`LifetimeRefMut::borrow_mut`], awaiting until it succeeds.
1100    pub async fn borrow_mut_async(&self) -> LifetimeRefMut {
1101        loop {
1102            if let Some(lifetime_ref_mut) = self.borrow_mut() {
1103                return lifetime_ref_mut;
1104            }
1105            poll_fn(|cx| {
1106                cx.waker().wake_by_ref();
1107                Poll::<LifetimeRefMut>::Pending
1108            })
1109            .await;
1110        }
1111    }
1112
1113    /// Takes a lazy handle to the same lifetime.
1114    pub fn lazy(&self) -> LifetimeLazy {
1115        LifetimeLazy(self.0.clone())
1116    }
1117
1118    /// Guards `data` for reading, or returns [`None`] while a write guard is
1119    /// live or the owner is gone.
1120    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
1121        let state = self.0.upgrade()?;
1122        let mut access = state.try_lock()?;
1123        if access.state.is_read_accessible() {
1124            access.acquire_read_access();
1125            drop(access);
1126            Some(ValueReadAccess {
1127                lifetime: state,
1128                data,
1129            })
1130        } else {
1131            None
1132        }
1133    }
1134
1135    /// [`LifetimeRefMut::read`], awaiting until it succeeds.
1136    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
1137        loop {
1138            if let Some(access) = self.read(data) {
1139                return access;
1140            }
1141            poll_fn(|cx| {
1142                cx.waker().wake_by_ref();
1143                Poll::<ValueReadAccess<'a, T>>::Pending
1144            })
1145            .await;
1146        }
1147    }
1148
1149    /// [`LifetimeRefMut::read`] over a raw pointer.
1150    ///
1151    /// # Safety
1152    ///
1153    /// `data` must stay valid and aligned for as long as the returned guard
1154    /// lives. A null pointer yields [`None`].
1155    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
1156        let data = unsafe { data.as_ref() }?;
1157        let state = self.0.upgrade()?;
1158        let mut access = state.try_lock()?;
1159        if access.state.is_read_accessible() {
1160            access.acquire_read_access();
1161            drop(access);
1162            Some(ValueReadAccess {
1163                lifetime: state,
1164                data,
1165            })
1166        } else {
1167            None
1168        }
1169    }
1170
1171    /// [`LifetimeRefMut::read_ptr`], awaiting until it succeeds.
1172    ///
1173    /// # Safety
1174    ///
1175    /// Same as [`LifetimeRefMut::read_ptr`], and `data` must also stay valid
1176    /// across every await point.
1177    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
1178        &'a self,
1179        data: *const T,
1180    ) -> ValueReadAccess<'a, T> {
1181        loop {
1182            if let Some(access) = unsafe { self.read_ptr(data) } {
1183                return access;
1184            }
1185            poll_fn(|cx| {
1186                cx.waker().wake_by_ref();
1187                Poll::<ValueReadAccess<'a, T>>::Pending
1188            })
1189            .await;
1190        }
1191    }
1192
1193    /// Guards `data` for writing, or returns [`None`] while any other access
1194    /// guard is live or the owner is gone.
1195    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
1196        let state = self.0.upgrade()?;
1197        let mut access = state.try_lock()?;
1198        if access.state.is_write_accessible() {
1199            access.acquire_write_access();
1200            drop(access);
1201            Some(ValueWriteAccess {
1202                lifetime: state,
1203                data,
1204            })
1205        } else {
1206            None
1207        }
1208    }
1209
1210    /// [`LifetimeRefMut::write`], awaiting until it succeeds.
1211    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
1212        unsafe { self.write_ptr_async(data as *mut T).await }
1213    }
1214
1215    /// [`LifetimeRefMut::write`] over a raw pointer.
1216    ///
1217    /// # Safety
1218    ///
1219    /// `data` must stay valid, aligned and unaliased for as long as the
1220    /// returned guard lives. A null pointer yields [`None`].
1221    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
1222        let data = unsafe { data.as_mut() }?;
1223        let state = self.0.upgrade()?;
1224        let mut access = state.try_lock()?;
1225        if access.state.is_write_accessible() {
1226            access.acquire_write_access();
1227            drop(access);
1228            Some(ValueWriteAccess {
1229                lifetime: state,
1230                data,
1231            })
1232        } else {
1233            None
1234        }
1235    }
1236
1237    /// [`LifetimeRefMut::write_ptr`], awaiting until it succeeds.
1238    ///
1239    /// # Safety
1240    ///
1241    /// Same as [`LifetimeRefMut::write_ptr`], and `data` must also stay valid
1242    /// across every await point.
1243    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
1244        &'a self,
1245        data: *mut T,
1246    ) -> ValueWriteAccess<'a, T> {
1247        loop {
1248            if let Some(access) = unsafe { self.write_ptr(data) } {
1249                return access;
1250            }
1251            poll_fn(|cx| {
1252                cx.waker().wake_by_ref();
1253                Poll::<ValueWriteAccess<'a, T>>::Pending
1254            })
1255            .await;
1256        }
1257    }
1258
1259    /// Claims read access without holding any data.
1260    pub fn try_read_lock(&self) -> Option<ReadLock> {
1261        let state = self.0.upgrade()?;
1262        let mut access = state.lock();
1263        if !access.state.is_read_accessible() {
1264            return None;
1265        }
1266        access.acquire_read_access();
1267        Some(ReadLock {
1268            lifetime: state.clone(),
1269        })
1270    }
1271
1272    /// [`LifetimeRefMut::try_read_lock`], spinning until it succeeds. Returns
1273    /// [`None`] when the owner is gone.
1274    pub fn read_lock(&self) -> Option<ReadLock> {
1275        let state = self.0.upgrade()?;
1276        let mut access = state.lock();
1277        while !access.state.is_read_accessible() {
1278            std::hint::spin_loop();
1279        }
1280        access.acquire_read_access();
1281        Some(ReadLock {
1282            lifetime: state.clone(),
1283        })
1284    }
1285
1286    /// [`LifetimeRefMut::read_lock`], awaiting until it succeeds.
1287    pub async fn read_lock_async(&self) -> ReadLock {
1288        loop {
1289            if let Some(lock) = self.read_lock() {
1290                return lock;
1291            }
1292            poll_fn(|cx| {
1293                cx.waker().wake_by_ref();
1294                Poll::<ReadLock>::Pending
1295            })
1296            .await;
1297        }
1298    }
1299
1300    /// Claims write access without holding any data.
1301    pub fn try_write_lock(&self) -> Option<WriteLock> {
1302        let state = self.0.upgrade()?;
1303        let mut access = state.lock();
1304        if !access.state.is_write_accessible() {
1305            return None;
1306        }
1307        access.acquire_write_access();
1308        Some(WriteLock {
1309            lifetime: state.clone(),
1310        })
1311    }
1312
1313    /// [`LifetimeRefMut::try_write_lock`], spinning until it succeeds. Returns
1314    /// [`None`] when the owner is gone.
1315    pub fn write_lock(&self) -> Option<WriteLock> {
1316        let state = self.0.upgrade()?;
1317        let mut access = state.lock();
1318        while !access.state.is_write_accessible() {
1319            std::hint::spin_loop();
1320        }
1321        access.acquire_write_access();
1322        Some(WriteLock {
1323            lifetime: state.clone(),
1324        })
1325    }
1326
1327    /// [`LifetimeRefMut::write_lock`], awaiting until it succeeds.
1328    pub async fn write_lock_async(&self) -> WriteLock {
1329        loop {
1330            if let Some(lock) = self.write_lock() {
1331                return lock;
1332            }
1333            poll_fn(|cx| {
1334                cx.waker().wake_by_ref();
1335                Poll::<WriteLock>::Pending
1336            })
1337            .await;
1338        }
1339    }
1340
1341    /// Turns this borrow into a write guard over `data` that lives as long as
1342    /// the borrow would have.
1343    ///
1344    /// Gives the borrow back unchanged when another access guard is live.
1345    pub fn consume<T: ?Sized>(self, data: &'_ mut T) -> Result<ValueWriteAccess<'_, T>, Self> {
1346        let state = match self.0.upgrade() {
1347            Some(state) => state,
1348            None => return Err(self),
1349        };
1350        let mut access = match state.try_lock() {
1351            Some(access) => access,
1352            None => return Err(self),
1353        };
1354        if access.state.is_write_accessible() {
1355            access.acquire_write_access();
1356            drop(access);
1357            Ok(ValueWriteAccess {
1358                lifetime: state,
1359                data,
1360            })
1361        } else {
1362            Err(self)
1363        }
1364    }
1365
1366    /// Awaits until reading would be allowed, or the owner is gone.
1367    pub async fn wait_for_read_access(&self) {
1368        loop {
1369            let Some(state) = self.0.upgrade() else {
1370                return;
1371            };
1372            if state.is_read_accessible() {
1373                return;
1374            }
1375            poll_fn(|cx| {
1376                cx.waker().wake_by_ref();
1377                Poll::<()>::Pending
1378            })
1379            .await;
1380        }
1381    }
1382
1383    /// Awaits until writing would be allowed, or the owner is gone.
1384    pub async fn wait_for_write_access(&self) {
1385        loop {
1386            let Some(state) = self.0.upgrade() else {
1387                return;
1388            };
1389            if state.is_write_accessible() {
1390                return;
1391            }
1392            poll_fn(|cx| {
1393                cx.waker().wake_by_ref();
1394                Poll::<()>::Pending
1395            })
1396            .await;
1397        }
1398    }
1399}
1400
1401/// Handle that claims nothing until it is used.
1402///
1403/// Unlike [`LifetimeRef`] and [`LifetimeRefMut`], holding one blocks
1404/// nobody, and it can be cloned freely. Each call checks the conditions
1405/// again, so it is the right handle for a value that is looked up now and
1406/// touched later, such as a script variable.
1407#[derive(Clone)]
1408pub struct LifetimeLazy(LifetimeWeakState);
1409
1410impl LifetimeLazy {
1411    /// Returns the weak state this handle points at.
1412    pub fn state(&self) -> &LifetimeWeakState {
1413        &self.0
1414    }
1415
1416    /// Returns the tag the owner had when this handle was taken.
1417    pub fn tag(&self) -> usize {
1418        self.0.tag
1419    }
1420
1421    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
1422    pub fn exists(&self) -> bool {
1423        self.0.upgrade().is_some()
1424    }
1425
1426    /// Returns `true` when no write guard is live.
1427    pub fn is_read_accessible(&self) -> bool {
1428        self.0
1429            .upgrade()
1430            .map(|state| state.is_read_accessible())
1431            .unwrap_or(false)
1432    }
1433
1434    /// Returns `true` when no access guard of any kind is live.
1435    pub fn is_write_accessible(&self) -> bool {
1436        self.0
1437            .upgrade()
1438            .map(|state| state.is_write_accessible())
1439            .unwrap_or(false)
1440    }
1441
1442    /// Returns `true` while any access guard is live.
1443    pub fn is_in_use(&self) -> bool {
1444        self.0
1445            .upgrade()
1446            .map(|state| state.is_in_use())
1447            .unwrap_or(false)
1448    }
1449
1450    /// Returns `true` when this handle came from `other`.
1451    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
1452        self.0.is_owned_by(&other.0)
1453    }
1454
1455    /// Upgrades to a real shared borrow.
1456    pub fn borrow(&self) -> Option<LifetimeRef> {
1457        self.0
1458            .upgrade()?
1459            .try_lock()
1460            .filter(|access| access.state.can_read())
1461            .map(|mut access| {
1462                access.acquire_reader();
1463                LifetimeRef(self.0.clone())
1464            })
1465    }
1466
1467    /// [`LifetimeLazy::borrow`], awaiting until it succeeds.
1468    pub async fn borrow_async(&self) -> LifetimeRef {
1469        loop {
1470            if let Some(lifetime_ref) = self.borrow() {
1471                return lifetime_ref;
1472            }
1473            poll_fn(|cx| {
1474                cx.waker().wake_by_ref();
1475                Poll::<LifetimeRef>::Pending
1476            })
1477            .await;
1478        }
1479    }
1480
1481    /// Upgrades to a real top level mutable borrow, which needs no other
1482    /// borrow to be out.
1483    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
1484        self.0
1485            .upgrade()?
1486            .try_lock()
1487            .filter(|access| access.state.can_write(0))
1488            .map(|mut access| {
1489                let id = access.acquire_writer();
1490                LifetimeRefMut(self.0.clone(), id)
1491            })
1492    }
1493
1494    /// [`LifetimeLazy::borrow_mut`], awaiting until it succeeds.
1495    pub async fn borrow_mut_async(&self) -> LifetimeRefMut {
1496        loop {
1497            if let Some(lifetime_ref_mut) = self.borrow_mut() {
1498                return lifetime_ref_mut;
1499            }
1500            poll_fn(|cx| {
1501                cx.waker().wake_by_ref();
1502                Poll::<LifetimeRefMut>::Pending
1503            })
1504            .await;
1505        }
1506    }
1507
1508    /// Guards `data` for reading, or returns [`None`] while a write guard is
1509    /// live or the owner is gone.
1510    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
1511        let state = self.0.upgrade()?;
1512        let mut access = state.try_lock()?;
1513        if access.state.is_read_accessible() {
1514            access.acquire_read_access();
1515            drop(access);
1516            Some(ValueReadAccess {
1517                lifetime: state,
1518                data,
1519            })
1520        } else {
1521            None
1522        }
1523    }
1524
1525    /// [`LifetimeLazy::read`], awaiting until it succeeds.
1526    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
1527        loop {
1528            if let Some(access) = self.read(data) {
1529                return access;
1530            }
1531            poll_fn(|cx| {
1532                cx.waker().wake_by_ref();
1533                Poll::<ValueReadAccess<'a, T>>::Pending
1534            })
1535            .await;
1536        }
1537    }
1538
1539    /// [`LifetimeLazy::read`] over a raw pointer.
1540    ///
1541    /// # Safety
1542    ///
1543    /// `data` must stay valid and aligned for as long as the returned guard
1544    /// lives. A null pointer yields [`None`].
1545    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
1546        let data = unsafe { data.as_ref() }?;
1547        let state = self.0.upgrade()?;
1548        let mut access = state.try_lock()?;
1549        if access.state.is_read_accessible() {
1550            access.acquire_read_access();
1551            drop(access);
1552            Some(ValueReadAccess {
1553                lifetime: state,
1554                data,
1555            })
1556        } else {
1557            None
1558        }
1559    }
1560
1561    /// [`LifetimeLazy::read_ptr`], awaiting until it succeeds.
1562    ///
1563    /// # Safety
1564    ///
1565    /// Same as [`LifetimeLazy::read_ptr`], and `data` must also stay valid
1566    /// across every await point.
1567    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
1568        &'a self,
1569        data: *const T,
1570    ) -> ValueReadAccess<'a, T> {
1571        loop {
1572            if let Some(access) = unsafe { self.read_ptr(data) } {
1573                return access;
1574            }
1575            poll_fn(|cx| {
1576                cx.waker().wake_by_ref();
1577                Poll::<ValueReadAccess<'a, T>>::Pending
1578            })
1579            .await;
1580        }
1581    }
1582
1583    /// Guards `data` for writing, or returns [`None`] while any other access
1584    /// guard is live or the owner is gone.
1585    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
1586        let state = self.0.upgrade()?;
1587        let mut access = state.try_lock()?;
1588        if access.state.is_write_accessible() {
1589            access.acquire_write_access();
1590            drop(access);
1591            Some(ValueWriteAccess {
1592                lifetime: state,
1593                data,
1594            })
1595        } else {
1596            None
1597        }
1598    }
1599
1600    /// [`LifetimeLazy::write`], awaiting until it succeeds.
1601    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
1602        unsafe { self.write_ptr_async(data as *mut T).await }
1603    }
1604
1605    /// [`LifetimeLazy::write`] over a raw pointer.
1606    ///
1607    /// # Safety
1608    ///
1609    /// `data` must stay valid, aligned and unaliased for as long as the
1610    /// returned guard lives. A null pointer yields [`None`].
1611    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
1612        let data = unsafe { data.as_mut() }?;
1613        let state = self.0.upgrade()?;
1614        let mut access = state.try_lock()?;
1615        if access.state.is_write_accessible() {
1616            access.acquire_write_access();
1617            drop(access);
1618            Some(ValueWriteAccess {
1619                lifetime: state,
1620                data,
1621            })
1622        } else {
1623            None
1624        }
1625    }
1626
1627    /// [`LifetimeLazy::write_ptr`], awaiting until it succeeds.
1628    ///
1629    /// # Safety
1630    ///
1631    /// Same as [`LifetimeLazy::write_ptr`], and `data` must also stay valid
1632    /// across every await point.
1633    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
1634        &'a self,
1635        data: *mut T,
1636    ) -> ValueWriteAccess<'a, T> {
1637        loop {
1638            if let Some(access) = unsafe { self.write_ptr(data) } {
1639                return access;
1640            }
1641            poll_fn(|cx| {
1642                cx.waker().wake_by_ref();
1643                Poll::<ValueWriteAccess<'a, T>>::Pending
1644            })
1645            .await;
1646        }
1647    }
1648
1649    /// Turns this handle into a write guard over `data`.
1650    ///
1651    /// Gives the handle back unchanged when another access guard is live.
1652    pub fn consume<T: ?Sized>(self, data: &'_ mut T) -> Result<ValueWriteAccess<'_, T>, Self> {
1653        let state = match self.0.upgrade() {
1654            Some(state) => state,
1655            None => return Err(self),
1656        };
1657        let mut access = match state.try_lock() {
1658            Some(access) => access,
1659            None => return Err(self),
1660        };
1661        if access.state.is_write_accessible() {
1662            access.acquire_write_access();
1663            drop(access);
1664            Ok(ValueWriteAccess {
1665                lifetime: state,
1666                data,
1667            })
1668        } else {
1669            Err(self)
1670        }
1671    }
1672
1673    /// Awaits until reading would be allowed, or the owner is gone.
1674    pub async fn wait_for_read_access(&self) {
1675        loop {
1676            let Some(state) = self.0.upgrade() else {
1677                return;
1678            };
1679            if state.is_read_accessible() {
1680                return;
1681            }
1682            poll_fn(|cx| {
1683                cx.waker().wake_by_ref();
1684                Poll::<()>::Pending
1685            })
1686            .await;
1687        }
1688    }
1689
1690    /// Awaits until writing would be allowed, or the owner is gone.
1691    pub async fn wait_for_write_access(&self) {
1692        loop {
1693            let Some(state) = self.0.upgrade() else {
1694                return;
1695            };
1696            if state.is_write_accessible() {
1697                return;
1698            }
1699            poll_fn(|cx| {
1700                cx.waker().wake_by_ref();
1701                Poll::<()>::Pending
1702            })
1703            .await;
1704        }
1705    }
1706}
1707
1708/// Read guard over a value, obtained from a lifetime or one of its handles.
1709///
1710/// Derefs to the value and releases the read claim on drop.
1711pub struct ValueReadAccess<'a, T: 'a + ?Sized> {
1712    lifetime: LifetimeState,
1713    data: &'a T,
1714}
1715
1716impl<T: ?Sized> Drop for ValueReadAccess<'_, T> {
1717    fn drop(&mut self) {
1718        self.lifetime.lock().release_read_access();
1719    }
1720}
1721
1722impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
1723    /// Builds a guard from parts, without going through the state checks.
1724    ///
1725    /// # Safety
1726    ///
1727    /// The read claim on `lifetime` must already be acquired, since dropping
1728    /// this guard releases one. `data` must be the value that `lifetime`
1729    /// guards.
1730    pub unsafe fn new_raw(data: &'a T, lifetime: LifetimeState) -> Self {
1731        Self { lifetime, data }
1732    }
1733}
1734
1735impl<T: ?Sized> Deref for ValueReadAccess<'_, T> {
1736    type Target = T;
1737
1738    fn deref(&self) -> &Self::Target {
1739        self.data
1740    }
1741}
1742
1743impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
1744    /// Narrows the guard down to a part of the value, for example one field.
1745    ///
1746    /// Gives the guard back unchanged when `f` returns [`None`].
1747    pub fn remap<U>(
1748        self,
1749        f: impl FnOnce(&T) -> Option<&U>,
1750    ) -> Result<ValueReadAccess<'a, U>, Self> {
1751        if let Some(data) = f(self.data) {
1752            Ok(ValueReadAccess {
1753                lifetime: self.lifetime.clone(),
1754                data,
1755            })
1756        } else {
1757            Err(self)
1758        }
1759    }
1760}
1761
1762/// Write guard over a value, obtained from a lifetime or one of its
1763/// handles.
1764///
1765/// Derefs to the value mutably and releases the write claim on drop.
1766/// While it is live no other access is allowed.
1767pub struct ValueWriteAccess<'a, T: 'a + ?Sized> {
1768    lifetime: LifetimeState,
1769    data: &'a mut T,
1770}
1771
1772impl<T: ?Sized> Drop for ValueWriteAccess<'_, T> {
1773    fn drop(&mut self) {
1774        self.lifetime.lock().release_write_access();
1775    }
1776}
1777
1778impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
1779    /// Builds a guard from parts, without going through the state checks.
1780    ///
1781    /// # Safety
1782    ///
1783    /// The write claim on `lifetime` must already be acquired, since dropping
1784    /// this guard releases one. `data` must be the value that `lifetime`
1785    /// guards, and must not be aliased.
1786    pub unsafe fn new_raw(data: &'a mut T, lifetime: LifetimeState) -> Self {
1787        Self { lifetime, data }
1788    }
1789}
1790
1791impl<T: ?Sized> Deref for ValueWriteAccess<'_, T> {
1792    type Target = T;
1793
1794    fn deref(&self) -> &Self::Target {
1795        self.data
1796    }
1797}
1798
1799impl<T: ?Sized> DerefMut for ValueWriteAccess<'_, T> {
1800    fn deref_mut(&mut self) -> &mut Self::Target {
1801        self.data
1802    }
1803}
1804
1805impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
1806    /// Narrows the guard down to a part of the value, for example one field.
1807    ///
1808    /// Gives the guard back unchanged when `f` returns [`None`].
1809    pub fn remap<U>(
1810        self,
1811        f: impl FnOnce(&mut T) -> Option<&mut U>,
1812    ) -> Result<ValueWriteAccess<'a, U>, Self> {
1813        if let Some(data) = f(unsafe { std::mem::transmute::<&mut T, &'a mut T>(&mut *self.data) })
1814        {
1815            Ok(ValueWriteAccess {
1816                lifetime: self.lifetime.clone(),
1817                data,
1818            })
1819        } else {
1820            Err(self)
1821        }
1822    }
1823}
1824
1825/// Read claim held without a reference to the value.
1826///
1827/// Useful for keeping a value readable across code that does not touch it.
1828/// Releases the claim on drop.
1829pub struct ReadLock {
1830    lifetime: LifetimeState,
1831}
1832
1833impl Drop for ReadLock {
1834    fn drop(&mut self) {
1835        self.lifetime.lock().release_read_access();
1836    }
1837}
1838
1839impl ReadLock {
1840    /// Builds a lock from a state, without going through the state checks.
1841    ///
1842    /// # Safety
1843    ///
1844    /// The read claim on `lifetime` must already be acquired, since dropping
1845    /// this lock releases one.
1846    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
1847        Self { lifetime }
1848    }
1849
1850    /// Runs `f` while holding the lock, then releases it.
1851    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
1852        let result = f();
1853        drop(self);
1854        result
1855    }
1856}
1857
1858/// Write claim held without a reference to the value.
1859///
1860/// Blocks every other access until dropped.
1861pub struct WriteLock {
1862    lifetime: LifetimeState,
1863}
1864
1865impl Drop for WriteLock {
1866    fn drop(&mut self) {
1867        self.lifetime.lock().release_write_access();
1868    }
1869}
1870
1871impl WriteLock {
1872    /// Builds a lock from a state, without going through the state checks.
1873    ///
1874    /// # Safety
1875    ///
1876    /// The write claim on `lifetime` must already be acquired, since dropping
1877    /// this lock releases one.
1878    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
1879        Self { lifetime }
1880    }
1881
1882    /// Runs `f` while holding the lock, then releases it.
1883    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
1884        let result = f();
1885        drop(self);
1886        result
1887    }
1888}
1889
1890#[cfg(test)]
1891mod tests {
1892    use super::*;
1893    use std::thread::*;
1894
1895    fn is_async<T: Send + Sync + ?Sized>() {
1896        println!("{} is async!", std::any::type_name::<T>());
1897    }
1898
1899    #[test]
1900    fn test_lifetimes() {
1901        is_async::<Lifetime>();
1902        is_async::<LifetimeRef>();
1903        is_async::<LifetimeRefMut>();
1904        is_async::<LifetimeLazy>();
1905
1906        let mut value = 0usize;
1907        let lifetime_ref = {
1908            let lifetime = Lifetime::default();
1909            assert!(lifetime.state().can_read());
1910            assert!(lifetime.state().can_write(0));
1911            assert!(lifetime.state().is_read_accessible());
1912            assert!(lifetime.state().is_write_accessible());
1913            let lifetime_lazy = lifetime.lazy();
1914            assert!(lifetime_lazy.read(&42).is_some());
1915            assert!(lifetime_lazy.write(&mut 42).is_some());
1916            {
1917                let access = lifetime.read(&value).unwrap();
1918                assert_eq!(*access, value);
1919            }
1920            {
1921                let mut access = lifetime.write(&mut value).unwrap();
1922                *access = 42;
1923                assert_eq!(*access, 42);
1924            }
1925            {
1926                let lifetime_ref = lifetime.borrow().unwrap();
1927                assert!(lifetime.state().can_read());
1928                assert!(!lifetime.state().can_write(0));
1929                assert!(lifetime_ref.exists());
1930                assert!(lifetime_ref.is_owned_by(&lifetime));
1931                assert!(lifetime.borrow().is_some());
1932                assert!(lifetime.borrow_mut().is_none());
1933                assert!(lifetime_lazy.read(&42).is_some());
1934                assert!(lifetime_lazy.write(&mut 42).is_some());
1935                {
1936                    let access = lifetime_ref.read(&value).unwrap();
1937                    assert_eq!(*access, 42);
1938                    assert!(lifetime_lazy.read(&42).is_some());
1939                    assert!(lifetime_lazy.write(&mut 42).is_none());
1940                }
1941                let lifetime_ref2 = lifetime_ref.borrow().unwrap();
1942                {
1943                    let access = lifetime_ref2.read(&value).unwrap();
1944                    assert_eq!(*access, 42);
1945                    assert!(lifetime_lazy.read(&42).is_some());
1946                    assert!(lifetime_lazy.write(&mut 42).is_none());
1947                }
1948            }
1949            {
1950                let lifetime_ref_mut = lifetime.borrow_mut().unwrap();
1951                assert_eq!(lifetime.state().writer_depth(), 1);
1952                assert!(!lifetime.state().can_read());
1953                assert!(!lifetime.state().can_write(0));
1954                assert!(lifetime_ref_mut.exists());
1955                assert!(lifetime_ref_mut.is_owned_by(&lifetime));
1956                assert!(lifetime.borrow().is_none());
1957                assert!(lifetime.borrow_mut().is_none());
1958                assert!(lifetime_lazy.read(&42).is_some());
1959                assert!(lifetime_lazy.write(&mut 42).is_some());
1960                {
1961                    let mut access = lifetime_ref_mut.write(&mut value).unwrap();
1962                    *access = 7;
1963                    assert_eq!(*access, 7);
1964                    assert!(lifetime_lazy.read(&42).is_none());
1965                    assert!(lifetime_lazy.write(&mut 42).is_none());
1966                }
1967                let lifetime_ref_mut2 = lifetime_ref_mut.borrow_mut().unwrap();
1968                assert!(lifetime_lazy.read(&42).is_some());
1969                assert!(lifetime_lazy.write(&mut 42).is_some());
1970                {
1971                    assert_eq!(lifetime.state().writer_depth(), 2);
1972                    assert!(lifetime.borrow().is_none());
1973                    assert!(lifetime_ref_mut.borrow().is_none());
1974                    assert!(lifetime.borrow_mut().is_none());
1975                    assert!(lifetime_ref_mut.borrow_mut().is_none());
1976                    let mut access = lifetime_ref_mut2.write(&mut value).unwrap();
1977                    *access = 42;
1978                    assert_eq!(*access, 42);
1979                    assert!(lifetime.read(&42).is_none());
1980                    assert!(lifetime_ref_mut.read(&42).is_none());
1981                    assert!(lifetime.write(&mut 42).is_none());
1982                    assert!(lifetime_ref_mut.write(&mut 42).is_none());
1983                    assert!(lifetime_lazy.read(&42).is_none());
1984                    assert!(lifetime_lazy.write(&mut 42).is_none());
1985                    assert!(lifetime_lazy.read(&42).is_none());
1986                    assert!(lifetime_lazy.write(&mut 42).is_none());
1987                }
1988            }
1989            assert_eq!(lifetime.state().writer_depth(), 0);
1990            lifetime.borrow().unwrap()
1991        };
1992        assert!(!lifetime_ref.exists());
1993        assert_eq!(value, 42);
1994    }
1995
1996    #[test]
1997    fn test_lifetimes_multithread() {
1998        let lifetime = Lifetime::default();
1999        let lifetime_ref = lifetime.borrow().unwrap();
2000        assert!(lifetime_ref.exists());
2001        assert!(lifetime_ref.is_owned_by(&lifetime));
2002        drop(lifetime);
2003        assert!(!lifetime_ref.exists());
2004        let lifetime = Lifetime::default();
2005        let lifetime = spawn(move || {
2006            let value_ref = lifetime.borrow().unwrap();
2007            assert!(value_ref.exists());
2008            assert!(value_ref.is_owned_by(&lifetime));
2009            lifetime
2010        })
2011        .join()
2012        .unwrap();
2013        assert!(!lifetime_ref.exists());
2014        assert!(!lifetime_ref.is_owned_by(&lifetime));
2015    }
2016
2017    #[test]
2018    fn test_lifetimes_move_invalidation() {
2019        let lifetime = Lifetime::default();
2020        let lifetime_ref = lifetime.borrow().unwrap();
2021        assert_eq!(lifetime_ref.tag(), lifetime.tag());
2022        assert!(lifetime_ref.exists());
2023        let lifetime_ref2 = lifetime_ref;
2024        assert_eq!(lifetime_ref2.tag(), lifetime.tag());
2025        assert!(lifetime_ref2.exists());
2026        let lifetime = Box::new(lifetime);
2027        assert_ne!(lifetime_ref2.tag(), lifetime.tag());
2028        assert!(!lifetime_ref2.exists());
2029        let lifetime = *lifetime;
2030        assert_ne!(lifetime_ref2.tag(), lifetime.tag());
2031        assert!(!lifetime_ref2.exists());
2032    }
2033
2034    #[pollster::test]
2035    async fn test_lifetime_async() {
2036        let mut value = 42usize;
2037        let lifetime = Lifetime::default();
2038        assert_eq!(*lifetime.read_async(&value).await, 42);
2039        {
2040            let lifetime_ref = lifetime.borrow_async().await;
2041            {
2042                let access = lifetime_ref.read_async(&value).await;
2043                assert_eq!(*access, 42);
2044            }
2045        }
2046        {
2047            let lifetime_ref_mut = lifetime.borrow_mut_async().await;
2048            {
2049                let mut access = lifetime_ref_mut.write_async(&mut value).await;
2050                *access = 7;
2051                assert_eq!(*access, 7);
2052            }
2053            assert_eq!(*lifetime.read_async(&value).await, 7);
2054        }
2055        {
2056            let mut access = lifetime.write_async(&mut value).await;
2057            *access = 84;
2058        }
2059        {
2060            let access = lifetime.read_async(&value).await;
2061            assert_eq!(*access, 84);
2062        }
2063    }
2064
2065    #[test]
2066    fn test_lifetime_locks() {
2067        let lifetime = Lifetime::default();
2068        assert!(lifetime.state().is_read_accessible());
2069        assert!(lifetime.state().is_write_accessible());
2070
2071        let read_lock = lifetime.read_lock();
2072        assert!(lifetime.state().is_read_accessible());
2073        assert!(!lifetime.state().is_write_accessible());
2074
2075        drop(read_lock);
2076        assert!(lifetime.state().is_read_accessible());
2077        assert!(lifetime.state().is_write_accessible());
2078
2079        let read_lock = lifetime.read_lock();
2080        assert!(lifetime.state().is_read_accessible());
2081        assert!(!lifetime.state().is_write_accessible());
2082
2083        let read_lock2 = lifetime.read_lock();
2084        assert!(lifetime.state().is_read_accessible());
2085        assert!(!lifetime.state().is_write_accessible());
2086
2087        drop(read_lock);
2088        assert!(lifetime.state().is_read_accessible());
2089        assert!(!lifetime.state().is_write_accessible());
2090
2091        drop(read_lock2);
2092        assert!(lifetime.state().is_read_accessible());
2093        assert!(lifetime.state().is_write_accessible());
2094
2095        let write_lock = lifetime.write_lock();
2096        assert!(!lifetime.state().is_read_accessible());
2097        assert!(!lifetime.state().is_write_accessible());
2098
2099        assert!(lifetime.try_read_lock().is_none());
2100        assert!(lifetime.try_write_lock().is_none());
2101
2102        drop(write_lock);
2103        assert!(lifetime.state().is_read_accessible());
2104        assert!(lifetime.state().is_write_accessible());
2105
2106        let data = ();
2107        let read_access = lifetime.read(&data).unwrap();
2108        assert!(lifetime.state().is_read_accessible());
2109        assert!(!lifetime.state().is_write_accessible());
2110        // the spin lock guards the counter update, not the guard's lifetime
2111        assert!(!lifetime.state().is_locked());
2112
2113        drop(read_access);
2114        assert!(lifetime.try_read_lock().is_some());
2115        assert!(lifetime.try_write_lock().is_some());
2116    }
2117
2118    #[test]
2119    fn test_read_access_guards_coexist() {
2120        let mut value = 42usize;
2121        let lifetime = Lifetime::default();
2122
2123        let first = lifetime.read(&value).unwrap();
2124        let second = lifetime.read(&value).unwrap();
2125        let third = lifetime.read(&value).unwrap();
2126        assert_eq!(*first, 42);
2127        assert_eq!(*second, 42);
2128        assert_eq!(*third, 42);
2129
2130        // no guard holds the spin lock, so nothing below spins or fails early
2131        assert!(!lifetime.state().is_locked());
2132        assert!(lifetime.state().is_read_accessible());
2133        // three readers still keep every writer out
2134        assert!(!lifetime.state().is_write_accessible());
2135        assert!(lifetime.try_write_lock().is_none());
2136        let lock = lifetime.try_read_lock().unwrap();
2137
2138        drop(lock);
2139        drop(third);
2140        drop(second);
2141        assert!(!lifetime.state().is_write_accessible());
2142        drop(first);
2143        assert!(lifetime.state().is_write_accessible());
2144
2145        *lifetime.write(&mut value).unwrap() = 10;
2146        assert_eq!(value, 10);
2147    }
2148
2149    #[test]
2150    fn test_write_access_guard_excludes_readers() {
2151        let mut value = 42usize;
2152        let lifetime = Lifetime::default();
2153
2154        let guard = lifetime.write(&mut value).unwrap();
2155        assert!(!lifetime.state().is_locked());
2156        assert!(!lifetime.state().is_read_accessible());
2157        assert!(lifetime.try_read_lock().is_none());
2158        assert!(lifetime.lazy().read(&0).is_none());
2159
2160        drop(guard);
2161        assert!(lifetime.state().is_read_accessible());
2162        assert!(lifetime.try_read_lock().is_some());
2163    }
2164
2165    #[test]
2166    fn test_null_pointer_leaves_no_access_behind() {
2167        let lifetime = Lifetime::default();
2168
2169        assert!(unsafe { lifetime.read_ptr(std::ptr::null::<usize>()) }.is_none());
2170        assert!(unsafe { lifetime.write_ptr(std::ptr::null_mut::<usize>()) }.is_none());
2171
2172        // a refused guard must not leave its count raised
2173        assert!(lifetime.state().is_read_accessible());
2174        assert!(lifetime.state().is_write_accessible());
2175        assert!(lifetime.try_write_lock().is_some());
2176    }
2177
2178    #[test]
2179    fn test_read_access_guards_across_threads() {
2180        let lifetime = Arc::new(Lifetime::default());
2181        let value = Arc::new(7usize);
2182
2183        let threads = (0..8)
2184            .map(|_| {
2185                let lifetime = lifetime.clone();
2186                let value = value.clone();
2187                spawn(move || {
2188                    let mut taken = 0usize;
2189                    for _ in 0..1000 {
2190                        if let Some(access) = lifetime.read(value.as_ref()) {
2191                            assert_eq!(*access, 7);
2192                            taken += 1;
2193                        }
2194                    }
2195                    taken
2196                })
2197            })
2198            .collect::<Vec<_>>();
2199        let total = threads
2200            .into_iter()
2201            .map(|thread| thread.join().unwrap())
2202            .sum::<usize>();
2203        assert!(total > 0);
2204
2205        // every guard is gone, so the counter has to be back at zero
2206        assert!(lifetime.state().is_write_accessible());
2207    }
2208}