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        if data.is_null() {
488            return None;
489        }
490        unsafe { self.0.update_tag(self) };
491        self.0
492            .try_lock()
493            .filter(|access| access.state.is_read_accessible())
494            .map(|mut access| {
495                access.acquire_read_access();
496                ValueReadAccess {
497                    lifetime: self.0.clone(),
498                    data: unsafe { &*data },
499                }
500            })
501    }
502
503    /// [`Lifetime::read_ptr`], awaiting until it succeeds.
504    ///
505    /// # Safety
506    ///
507    /// Same as [`Lifetime::read_ptr`], and `data` must also stay valid across
508    /// every await point.
509    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
510        &'a self,
511        data: *const T,
512    ) -> ValueReadAccess<'a, T> {
513        loop {
514            if let Some(access) = unsafe { self.read_ptr(data) } {
515                return access;
516            }
517            poll_fn(|cx| {
518                cx.waker().wake_by_ref();
519                Poll::<ValueReadAccess<'a, T>>::Pending
520            })
521            .await;
522        }
523    }
524
525    /// Guards `data` for writing, or returns [`None`] while any other access
526    /// guard is live.
527    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
528        unsafe { self.0.update_tag(self) };
529        self.0
530            .try_lock()
531            .filter(|access| access.state.is_write_accessible())
532            .map(|mut access| {
533                access.acquire_write_access();
534                ValueWriteAccess {
535                    lifetime: self.0.clone(),
536                    data,
537                }
538            })
539    }
540
541    /// [`Lifetime::write`], awaiting until it succeeds.
542    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
543        unsafe { self.write_ptr_async(data as *mut T).await }
544    }
545
546    /// [`Lifetime::write`] over a raw pointer.
547    ///
548    /// # Safety
549    ///
550    /// `data` must stay valid, aligned and unaliased for as long as the
551    /// returned guard lives. A null pointer yields [`None`].
552    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
553        if data.is_null() {
554            return None;
555        }
556        unsafe { self.0.update_tag(self) };
557        self.0
558            .try_lock()
559            .filter(|access| access.state.is_write_accessible())
560            .map(|mut access| {
561                access.acquire_write_access();
562                ValueWriteAccess {
563                    lifetime: self.0.clone(),
564                    data: unsafe { &mut *data },
565                }
566            })
567    }
568
569    /// [`Lifetime::write_ptr`], awaiting until it succeeds.
570    ///
571    /// # Safety
572    ///
573    /// Same as [`Lifetime::write_ptr`], and `data` must also stay valid across
574    /// every await point.
575    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
576        &'a self,
577        data: *mut T,
578    ) -> ValueWriteAccess<'a, T> {
579        loop {
580            if let Some(access) = unsafe { self.write_ptr(data) } {
581                return access;
582            }
583            poll_fn(|cx| {
584                cx.waker().wake_by_ref();
585                Poll::<ValueWriteAccess<'a, T>>::Pending
586            })
587            .await;
588        }
589    }
590
591    /// Claims read access without holding any data, or returns [`None`] when a
592    /// write guard is live.
593    pub fn try_read_lock(&self) -> Option<ReadLock> {
594        unsafe { self.0.update_tag(self) };
595        let mut access = self.0.lock();
596        if !access.state.is_read_accessible() {
597            return None;
598        }
599        access.acquire_read_access();
600        Some(ReadLock {
601            lifetime: self.0.clone(),
602        })
603    }
604
605    /// [`Lifetime::try_read_lock`], spinning until it succeeds.
606    pub fn read_lock(&self) -> ReadLock {
607        unsafe { self.0.update_tag(self) };
608        let mut access = self.0.lock();
609        while !access.state.is_read_accessible() {
610            std::hint::spin_loop();
611        }
612        access.acquire_read_access();
613        ReadLock {
614            lifetime: self.0.clone(),
615        }
616    }
617
618    /// [`Lifetime::try_read_lock`], awaiting until it succeeds.
619    pub async fn read_lock_async(&self) -> ReadLock {
620        loop {
621            unsafe { self.0.update_tag(self) };
622            let mut access = self.0.lock();
623            if access.state.is_read_accessible() {
624                access.acquire_read_access();
625                return ReadLock {
626                    lifetime: self.0.clone(),
627                };
628            }
629            poll_fn(|cx| {
630                cx.waker().wake_by_ref();
631                Poll::<ReadLock>::Pending
632            })
633            .await;
634        }
635    }
636
637    /// Claims write access without holding any data, or returns [`None`] when
638    /// any access guard is live.
639    pub fn try_write_lock(&self) -> Option<WriteLock> {
640        unsafe { self.0.update_tag(self) };
641        let mut access = self.0.lock();
642        if !access.state.is_write_accessible() {
643            return None;
644        }
645        access.acquire_write_access();
646        Some(WriteLock {
647            lifetime: self.0.clone(),
648        })
649    }
650
651    /// [`Lifetime::try_write_lock`], spinning until it succeeds.
652    pub fn write_lock(&self) -> WriteLock {
653        unsafe { self.0.update_tag(self) };
654        let mut access = self.0.lock();
655        while !access.state.is_write_accessible() {
656            std::hint::spin_loop();
657        }
658        access.acquire_write_access();
659        WriteLock {
660            lifetime: self.0.clone(),
661        }
662    }
663
664    /// [`Lifetime::try_write_lock`], awaiting until it succeeds.
665    pub async fn write_lock_async(&self) -> WriteLock {
666        loop {
667            unsafe { self.0.update_tag(self) };
668            let mut access = self.0.lock();
669            if access.state.is_write_accessible() {
670                access.acquire_write_access();
671                return WriteLock {
672                    lifetime: self.0.clone(),
673                };
674            }
675            poll_fn(|cx| {
676                cx.waker().wake_by_ref();
677                Poll::<WriteLock>::Pending
678            })
679            .await;
680        }
681    }
682
683    /// Awaits until reading would be allowed, without claiming anything.
684    pub async fn wait_for_read_access(&self) {
685        loop {
686            if self.state().is_read_accessible() {
687                return;
688            }
689            poll_fn(|cx| {
690                cx.waker().wake_by_ref();
691                Poll::<()>::Pending
692            })
693            .await;
694        }
695    }
696
697    /// Awaits until writing would be allowed, without claiming anything.
698    pub async fn wait_for_write_access(&self) {
699        loop {
700            if self.state().is_write_accessible() {
701                return;
702            }
703            poll_fn(|cx| {
704                cx.waker().wake_by_ref();
705                Poll::<()>::Pending
706            })
707            .await;
708        }
709    }
710}
711
712/// Shared borrow of a [`Lifetime`], the runtime analogue of `&T`.
713///
714/// Many can coexist and they keep mutable borrows out. Releases its claim
715/// on drop.
716pub struct LifetimeRef(LifetimeWeakState);
717
718impl Drop for LifetimeRef {
719    fn drop(&mut self) {
720        if let Some(owner) = unsafe { self.0.upgrade_unchecked() }
721            && let Some(mut access) = owner.try_lock()
722        {
723            access.release_reader();
724        }
725    }
726}
727
728impl LifetimeRef {
729    /// Returns the weak state this borrow points at.
730    pub fn state(&self) -> &LifetimeWeakState {
731        &self.0
732    }
733
734    /// Returns the tag the owner had when this borrow was taken.
735    pub fn tag(&self) -> usize {
736        self.0.tag
737    }
738
739    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
740    pub fn exists(&self) -> bool {
741        self.0.upgrade().is_some()
742    }
743
744    /// Returns `true` when another shared borrow could be taken.
745    pub fn can_read(&self) -> bool {
746        self.0
747            .upgrade()
748            .map(|state| state.can_read())
749            .unwrap_or(false)
750    }
751
752    /// Returns `true` when no write guard is live.
753    pub fn is_read_accessible(&self) -> bool {
754        self.0
755            .upgrade()
756            .map(|state| state.is_read_accessible())
757            .unwrap_or(false)
758    }
759
760    /// Returns `true` while any access guard is live.
761    pub fn is_in_use(&self) -> bool {
762        self.0
763            .upgrade()
764            .map(|state| state.is_in_use())
765            .unwrap_or(false)
766    }
767
768    /// Returns `true` when this borrow came from `other`.
769    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
770        self.0.is_owned_by(&other.0)
771    }
772
773    /// Takes another shared borrow of the same lifetime.
774    pub fn borrow(&self) -> Option<LifetimeRef> {
775        self.0
776            .upgrade()?
777            .try_lock()
778            .filter(|access| access.state.can_read())
779            .map(|mut access| {
780                access.acquire_reader();
781                LifetimeRef(self.0.clone())
782            })
783    }
784
785    /// [`LifetimeRef::borrow`], awaiting until it succeeds.
786    pub async fn borrow_async(&self) -> LifetimeRef {
787        loop {
788            if let Some(lifetime_ref) = self.borrow() {
789                return lifetime_ref;
790            }
791            poll_fn(|cx| {
792                cx.waker().wake_by_ref();
793                Poll::<LifetimeRef>::Pending
794            })
795            .await;
796        }
797    }
798
799    /// Takes a lazy handle to the same lifetime.
800    pub fn lazy(&self) -> LifetimeLazy {
801        LifetimeLazy(self.0.clone())
802    }
803
804    /// Guards `data` for reading, or returns [`None`] while a write guard is
805    /// live or the owner is gone.
806    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
807        let state = self.0.upgrade()?;
808        let mut access = state.try_lock()?;
809        if access.state.is_read_accessible() {
810            access.acquire_read_access();
811            drop(access);
812            Some(ValueReadAccess {
813                lifetime: state,
814                data,
815            })
816        } else {
817            None
818        }
819    }
820
821    /// [`LifetimeRef::read`], awaiting until it succeeds.
822    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
823        loop {
824            if let Some(access) = self.read(data) {
825                return access;
826            }
827            poll_fn(|cx| {
828                cx.waker().wake_by_ref();
829                Poll::<ValueReadAccess<'a, T>>::Pending
830            })
831            .await;
832        }
833    }
834
835    /// [`LifetimeRef::read`] over a raw pointer.
836    ///
837    /// # Safety
838    ///
839    /// `data` must stay valid and aligned for as long as the returned guard
840    /// lives. A null pointer yields [`None`].
841    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
842        // The upgrade must happen before the pointer becomes a reference. The
843        // owner can already be gone, and a reference into freed memory is
844        // undefined behavior even when this function then returns `None`.
845        if data.is_null() {
846            return None;
847        }
848        let state = self.0.upgrade()?;
849        let mut access = state.try_lock()?;
850        if access.state.is_read_accessible() {
851            access.acquire_read_access();
852            drop(access);
853            Some(ValueReadAccess {
854                lifetime: state,
855                data: unsafe { &*data },
856            })
857        } else {
858            None
859        }
860    }
861
862    /// [`LifetimeRef::read_ptr`], awaiting until it succeeds.
863    ///
864    /// # Safety
865    ///
866    /// Same as [`LifetimeRef::read_ptr`], and `data` must also stay valid
867    /// across every await point.
868    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
869        &'a self,
870        data: *const T,
871    ) -> ValueReadAccess<'a, T> {
872        loop {
873            if let Some(access) = unsafe { self.read_ptr(data) } {
874                return access;
875            }
876            poll_fn(|cx| {
877                cx.waker().wake_by_ref();
878                Poll::<ValueReadAccess<'a, T>>::Pending
879            })
880            .await;
881        }
882    }
883
884    /// Claims read access without holding any data.
885    pub fn try_read_lock(&self) -> Option<ReadLock> {
886        let state = self.0.upgrade()?;
887        let mut access = state.lock();
888        if !access.state.is_read_accessible() {
889            return None;
890        }
891        access.acquire_read_access();
892        Some(ReadLock {
893            lifetime: state.clone(),
894        })
895    }
896
897    /// [`LifetimeRef::try_read_lock`], spinning until it succeeds. Returns
898    /// [`None`] when the owner is gone.
899    pub fn read_lock(&self) -> Option<ReadLock> {
900        let state = self.0.upgrade()?;
901        let mut access = state.lock();
902        while !access.state.is_read_accessible() {
903            std::hint::spin_loop();
904        }
905        access.acquire_read_access();
906        Some(ReadLock {
907            lifetime: state.clone(),
908        })
909    }
910
911    /// [`LifetimeRef::read_lock`], awaiting until it succeeds.
912    pub async fn read_lock_async(&self) -> ReadLock {
913        loop {
914            if let Some(lock) = self.read_lock() {
915                return lock;
916            }
917            poll_fn(|cx| {
918                cx.waker().wake_by_ref();
919                Poll::<ReadLock>::Pending
920            })
921            .await;
922        }
923    }
924
925    /// Turns this borrow into a read guard over `data` that lives as long as
926    /// the borrow would have.
927    ///
928    /// Gives the borrow back unchanged when a write guard is live.
929    pub fn consume<T: ?Sized>(self, data: &'_ T) -> Result<ValueReadAccess<'_, T>, Self> {
930        let state = match self.0.upgrade() {
931            Some(state) => state,
932            None => return Err(self),
933        };
934        let mut access = match state.try_lock() {
935            Some(access) => access,
936            None => return Err(self),
937        };
938        if access.state.is_read_accessible() {
939            access.acquire_read_access();
940            drop(access);
941            Ok(ValueReadAccess {
942                lifetime: state,
943                data,
944            })
945        } else {
946            Err(self)
947        }
948    }
949
950    /// Awaits until reading would be allowed, or the owner is gone.
951    pub async fn wait_for_read_access(&self) {
952        loop {
953            let Some(state) = self.0.upgrade() else {
954                return;
955            };
956            if state.is_read_accessible() {
957                return;
958            }
959            poll_fn(|cx| {
960                cx.waker().wake_by_ref();
961                Poll::<()>::Pending
962            })
963            .await;
964        }
965    }
966
967    /// Awaits until writing would be allowed, or the owner is gone.
968    pub async fn wait_for_write_access(&self) {
969        loop {
970            let Some(state) = self.0.upgrade() else {
971                return;
972            };
973            if state.is_write_accessible() {
974                return;
975            }
976            poll_fn(|cx| {
977                cx.waker().wake_by_ref();
978                Poll::<()>::Pending
979            })
980            .await;
981        }
982    }
983}
984
985/// Mutable borrow of a [`Lifetime`], the runtime analogue of `&mut T`.
986///
987/// Excludes every other top level borrow, but can reborrow itself through
988/// [`LifetimeRefMut::borrow_mut`], which nests one level deeper. Releases
989/// its level, and everything nested under it, on drop.
990pub struct LifetimeRefMut(LifetimeWeakState, usize);
991
992impl Drop for LifetimeRefMut {
993    fn drop(&mut self) {
994        if let Some(state) = unsafe { self.0.upgrade_unchecked() }
995            && let Some(mut access) = state.try_lock()
996        {
997            access.release_writer(self.1);
998        }
999    }
1000}
1001
1002impl LifetimeRefMut {
1003    /// Returns the weak state this borrow points at.
1004    pub fn state(&self) -> &LifetimeWeakState {
1005        &self.0
1006    }
1007
1008    /// Returns the tag the owner had when this borrow was taken.
1009    pub fn tag(&self) -> usize {
1010        self.0.tag
1011    }
1012
1013    /// Returns how deeply this mutable borrow is nested, starting at `1`.
1014    pub fn depth(&self) -> usize {
1015        self.1
1016    }
1017
1018    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
1019    pub fn exists(&self) -> bool {
1020        self.0.upgrade().is_some()
1021    }
1022
1023    /// Returns `true` when a shared borrow could be taken.
1024    pub fn can_read(&self) -> bool {
1025        self.0
1026            .upgrade()
1027            .map(|state| state.can_read())
1028            .unwrap_or(false)
1029    }
1030
1031    /// Returns `true` when this borrow could be reborrowed mutably.
1032    pub fn can_write(&self) -> bool {
1033        self.0
1034            .upgrade()
1035            .map(|state| state.can_write(self.1))
1036            .unwrap_or(false)
1037    }
1038
1039    /// Returns `true` when no write guard is live.
1040    pub fn is_read_accessible(&self) -> bool {
1041        self.0
1042            .upgrade()
1043            .map(|state| state.is_read_accessible())
1044            .unwrap_or(false)
1045    }
1046
1047    /// Returns `true` when no access guard of any kind is live.
1048    pub fn is_write_accessible(&self) -> bool {
1049        self.0
1050            .upgrade()
1051            .map(|state| state.is_write_accessible())
1052            .unwrap_or(false)
1053    }
1054
1055    /// Returns `true` while any access guard is live.
1056    pub fn is_in_use(&self) -> bool {
1057        self.0
1058            .upgrade()
1059            .map(|state| state.is_in_use())
1060            .unwrap_or(false)
1061    }
1062
1063    /// Returns `true` when this borrow came from `other`.
1064    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
1065        self.0.is_owned_by(&other.0)
1066    }
1067
1068    /// Takes a shared borrow, which only succeeds once this mutable borrow is
1069    /// not the innermost one.
1070    pub fn borrow(&self) -> Option<LifetimeRef> {
1071        self.0
1072            .upgrade()?
1073            .try_lock()
1074            .filter(|access| access.state.can_read())
1075            .map(|mut access| {
1076                access.acquire_reader();
1077                LifetimeRef(self.0.clone())
1078            })
1079    }
1080
1081    /// [`LifetimeRefMut::borrow`], awaiting until it succeeds.
1082    pub async fn borrow_async(&self) -> LifetimeRef {
1083        loop {
1084            if let Some(lifetime_ref) = self.borrow() {
1085                return lifetime_ref;
1086            }
1087            poll_fn(|cx| {
1088                cx.waker().wake_by_ref();
1089                Poll::<LifetimeRef>::Pending
1090            })
1091            .await;
1092        }
1093    }
1094
1095    /// Reborrows mutably one level deeper, or returns [`None`] when this is not
1096    /// the innermost mutable borrow.
1097    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
1098        self.0
1099            .upgrade()?
1100            .try_lock()
1101            .filter(|access| access.state.can_write(self.1))
1102            .map(|mut access| {
1103                let id = access.acquire_writer();
1104                LifetimeRefMut(self.0.clone(), id)
1105            })
1106    }
1107
1108    /// [`LifetimeRefMut::borrow_mut`], awaiting until it succeeds.
1109    pub async fn borrow_mut_async(&self) -> LifetimeRefMut {
1110        loop {
1111            if let Some(lifetime_ref_mut) = self.borrow_mut() {
1112                return lifetime_ref_mut;
1113            }
1114            poll_fn(|cx| {
1115                cx.waker().wake_by_ref();
1116                Poll::<LifetimeRefMut>::Pending
1117            })
1118            .await;
1119        }
1120    }
1121
1122    /// Takes a lazy handle to the same lifetime.
1123    pub fn lazy(&self) -> LifetimeLazy {
1124        LifetimeLazy(self.0.clone())
1125    }
1126
1127    /// Guards `data` for reading, or returns [`None`] while a write guard is
1128    /// live or the owner is gone.
1129    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
1130        let state = self.0.upgrade()?;
1131        let mut access = state.try_lock()?;
1132        if access.state.is_read_accessible() {
1133            access.acquire_read_access();
1134            drop(access);
1135            Some(ValueReadAccess {
1136                lifetime: state,
1137                data,
1138            })
1139        } else {
1140            None
1141        }
1142    }
1143
1144    /// [`LifetimeRefMut::read`], awaiting until it succeeds.
1145    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
1146        loop {
1147            if let Some(access) = self.read(data) {
1148                return access;
1149            }
1150            poll_fn(|cx| {
1151                cx.waker().wake_by_ref();
1152                Poll::<ValueReadAccess<'a, T>>::Pending
1153            })
1154            .await;
1155        }
1156    }
1157
1158    /// [`LifetimeRefMut::read`] over a raw pointer.
1159    ///
1160    /// # Safety
1161    ///
1162    /// `data` must stay valid and aligned for as long as the returned guard
1163    /// lives. A null pointer yields [`None`].
1164    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
1165        // The upgrade must happen before the pointer becomes a reference. The
1166        // owner can already be gone, and a reference into freed memory is
1167        // undefined behavior even when this function then returns `None`.
1168        if data.is_null() {
1169            return None;
1170        }
1171        let state = self.0.upgrade()?;
1172        let mut access = state.try_lock()?;
1173        if access.state.is_read_accessible() {
1174            access.acquire_read_access();
1175            drop(access);
1176            Some(ValueReadAccess {
1177                lifetime: state,
1178                data: unsafe { &*data },
1179            })
1180        } else {
1181            None
1182        }
1183    }
1184
1185    /// [`LifetimeRefMut::read_ptr`], awaiting until it succeeds.
1186    ///
1187    /// # Safety
1188    ///
1189    /// Same as [`LifetimeRefMut::read_ptr`], and `data` must also stay valid
1190    /// across every await point.
1191    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
1192        &'a self,
1193        data: *const T,
1194    ) -> ValueReadAccess<'a, T> {
1195        loop {
1196            if let Some(access) = unsafe { self.read_ptr(data) } {
1197                return access;
1198            }
1199            poll_fn(|cx| {
1200                cx.waker().wake_by_ref();
1201                Poll::<ValueReadAccess<'a, T>>::Pending
1202            })
1203            .await;
1204        }
1205    }
1206
1207    /// Guards `data` for writing, or returns [`None`] while any other access
1208    /// guard is live or the owner is gone.
1209    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
1210        let state = self.0.upgrade()?;
1211        let mut access = state.try_lock()?;
1212        if access.state.is_write_accessible() {
1213            access.acquire_write_access();
1214            drop(access);
1215            Some(ValueWriteAccess {
1216                lifetime: state,
1217                data,
1218            })
1219        } else {
1220            None
1221        }
1222    }
1223
1224    /// [`LifetimeRefMut::write`], awaiting until it succeeds.
1225    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
1226        unsafe { self.write_ptr_async(data as *mut T).await }
1227    }
1228
1229    /// [`LifetimeRefMut::write`] over a raw pointer.
1230    ///
1231    /// # Safety
1232    ///
1233    /// `data` must stay valid, aligned and unaliased for as long as the
1234    /// returned guard lives. A null pointer yields [`None`].
1235    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
1236        // The upgrade must happen before the pointer becomes a reference. The
1237        // owner can already be gone, and a reference into freed memory is
1238        // undefined behavior even when this function then returns `None`.
1239        if data.is_null() {
1240            return None;
1241        }
1242        let state = self.0.upgrade()?;
1243        let mut access = state.try_lock()?;
1244        if access.state.is_write_accessible() {
1245            access.acquire_write_access();
1246            drop(access);
1247            Some(ValueWriteAccess {
1248                lifetime: state,
1249                data: unsafe { &mut *data },
1250            })
1251        } else {
1252            None
1253        }
1254    }
1255
1256    /// [`LifetimeRefMut::write_ptr`], awaiting until it succeeds.
1257    ///
1258    /// # Safety
1259    ///
1260    /// Same as [`LifetimeRefMut::write_ptr`], and `data` must also stay valid
1261    /// across every await point.
1262    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
1263        &'a self,
1264        data: *mut T,
1265    ) -> ValueWriteAccess<'a, T> {
1266        loop {
1267            if let Some(access) = unsafe { self.write_ptr(data) } {
1268                return access;
1269            }
1270            poll_fn(|cx| {
1271                cx.waker().wake_by_ref();
1272                Poll::<ValueWriteAccess<'a, T>>::Pending
1273            })
1274            .await;
1275        }
1276    }
1277
1278    /// Claims read access without holding any data.
1279    pub fn try_read_lock(&self) -> Option<ReadLock> {
1280        let state = self.0.upgrade()?;
1281        let mut access = state.lock();
1282        if !access.state.is_read_accessible() {
1283            return None;
1284        }
1285        access.acquire_read_access();
1286        Some(ReadLock {
1287            lifetime: state.clone(),
1288        })
1289    }
1290
1291    /// [`LifetimeRefMut::try_read_lock`], spinning until it succeeds. Returns
1292    /// [`None`] when the owner is gone.
1293    pub fn read_lock(&self) -> Option<ReadLock> {
1294        let state = self.0.upgrade()?;
1295        let mut access = state.lock();
1296        while !access.state.is_read_accessible() {
1297            std::hint::spin_loop();
1298        }
1299        access.acquire_read_access();
1300        Some(ReadLock {
1301            lifetime: state.clone(),
1302        })
1303    }
1304
1305    /// [`LifetimeRefMut::read_lock`], awaiting until it succeeds.
1306    pub async fn read_lock_async(&self) -> ReadLock {
1307        loop {
1308            if let Some(lock) = self.read_lock() {
1309                return lock;
1310            }
1311            poll_fn(|cx| {
1312                cx.waker().wake_by_ref();
1313                Poll::<ReadLock>::Pending
1314            })
1315            .await;
1316        }
1317    }
1318
1319    /// Claims write access without holding any data.
1320    pub fn try_write_lock(&self) -> Option<WriteLock> {
1321        let state = self.0.upgrade()?;
1322        let mut access = state.lock();
1323        if !access.state.is_write_accessible() {
1324            return None;
1325        }
1326        access.acquire_write_access();
1327        Some(WriteLock {
1328            lifetime: state.clone(),
1329        })
1330    }
1331
1332    /// [`LifetimeRefMut::try_write_lock`], spinning until it succeeds. Returns
1333    /// [`None`] when the owner is gone.
1334    pub fn write_lock(&self) -> Option<WriteLock> {
1335        let state = self.0.upgrade()?;
1336        let mut access = state.lock();
1337        while !access.state.is_write_accessible() {
1338            std::hint::spin_loop();
1339        }
1340        access.acquire_write_access();
1341        Some(WriteLock {
1342            lifetime: state.clone(),
1343        })
1344    }
1345
1346    /// [`LifetimeRefMut::write_lock`], awaiting until it succeeds.
1347    pub async fn write_lock_async(&self) -> WriteLock {
1348        loop {
1349            if let Some(lock) = self.write_lock() {
1350                return lock;
1351            }
1352            poll_fn(|cx| {
1353                cx.waker().wake_by_ref();
1354                Poll::<WriteLock>::Pending
1355            })
1356            .await;
1357        }
1358    }
1359
1360    /// Turns this borrow into a write guard over `data` that lives as long as
1361    /// the borrow would have.
1362    ///
1363    /// Gives the borrow back unchanged when another access guard is live.
1364    pub fn consume<T: ?Sized>(self, data: &'_ mut T) -> Result<ValueWriteAccess<'_, T>, Self> {
1365        let state = match self.0.upgrade() {
1366            Some(state) => state,
1367            None => return Err(self),
1368        };
1369        let mut access = match state.try_lock() {
1370            Some(access) => access,
1371            None => return Err(self),
1372        };
1373        if access.state.is_write_accessible() {
1374            access.acquire_write_access();
1375            drop(access);
1376            Ok(ValueWriteAccess {
1377                lifetime: state,
1378                data,
1379            })
1380        } else {
1381            Err(self)
1382        }
1383    }
1384
1385    /// Awaits until reading would be allowed, or the owner is gone.
1386    pub async fn wait_for_read_access(&self) {
1387        loop {
1388            let Some(state) = self.0.upgrade() else {
1389                return;
1390            };
1391            if state.is_read_accessible() {
1392                return;
1393            }
1394            poll_fn(|cx| {
1395                cx.waker().wake_by_ref();
1396                Poll::<()>::Pending
1397            })
1398            .await;
1399        }
1400    }
1401
1402    /// Awaits until writing would be allowed, or the owner is gone.
1403    pub async fn wait_for_write_access(&self) {
1404        loop {
1405            let Some(state) = self.0.upgrade() else {
1406                return;
1407            };
1408            if state.is_write_accessible() {
1409                return;
1410            }
1411            poll_fn(|cx| {
1412                cx.waker().wake_by_ref();
1413                Poll::<()>::Pending
1414            })
1415            .await;
1416        }
1417    }
1418}
1419
1420/// Handle that claims nothing until it is used.
1421///
1422/// Unlike [`LifetimeRef`] and [`LifetimeRefMut`], holding one blocks
1423/// nobody, and it can be cloned freely. Each call checks the conditions
1424/// again, so it is the right handle for a value that is looked up now and
1425/// touched later, such as a script variable.
1426#[derive(Clone)]
1427pub struct LifetimeLazy(LifetimeWeakState);
1428
1429impl LifetimeLazy {
1430    /// Returns the weak state this handle points at.
1431    pub fn state(&self) -> &LifetimeWeakState {
1432        &self.0
1433    }
1434
1435    /// Returns the tag the owner had when this handle was taken.
1436    pub fn tag(&self) -> usize {
1437        self.0.tag
1438    }
1439
1440    /// Returns `true` while the owning [`Lifetime`] is alive and valid.
1441    pub fn exists(&self) -> bool {
1442        self.0.upgrade().is_some()
1443    }
1444
1445    /// Returns `true` when no write guard is live.
1446    pub fn is_read_accessible(&self) -> bool {
1447        self.0
1448            .upgrade()
1449            .map(|state| state.is_read_accessible())
1450            .unwrap_or(false)
1451    }
1452
1453    /// Returns `true` when no access guard of any kind is live.
1454    pub fn is_write_accessible(&self) -> bool {
1455        self.0
1456            .upgrade()
1457            .map(|state| state.is_write_accessible())
1458            .unwrap_or(false)
1459    }
1460
1461    /// Returns `true` while any access guard is live.
1462    pub fn is_in_use(&self) -> bool {
1463        self.0
1464            .upgrade()
1465            .map(|state| state.is_in_use())
1466            .unwrap_or(false)
1467    }
1468
1469    /// Returns `true` when this handle came from `other`.
1470    pub fn is_owned_by(&self, other: &Lifetime) -> bool {
1471        self.0.is_owned_by(&other.0)
1472    }
1473
1474    /// Upgrades to a real shared borrow.
1475    pub fn borrow(&self) -> Option<LifetimeRef> {
1476        self.0
1477            .upgrade()?
1478            .try_lock()
1479            .filter(|access| access.state.can_read())
1480            .map(|mut access| {
1481                access.acquire_reader();
1482                LifetimeRef(self.0.clone())
1483            })
1484    }
1485
1486    /// [`LifetimeLazy::borrow`], awaiting until it succeeds.
1487    pub async fn borrow_async(&self) -> LifetimeRef {
1488        loop {
1489            if let Some(lifetime_ref) = self.borrow() {
1490                return lifetime_ref;
1491            }
1492            poll_fn(|cx| {
1493                cx.waker().wake_by_ref();
1494                Poll::<LifetimeRef>::Pending
1495            })
1496            .await;
1497        }
1498    }
1499
1500    /// Upgrades to a real top level mutable borrow, which needs no other
1501    /// borrow to be out.
1502    pub fn borrow_mut(&self) -> Option<LifetimeRefMut> {
1503        self.0
1504            .upgrade()?
1505            .try_lock()
1506            .filter(|access| access.state.can_write(0))
1507            .map(|mut access| {
1508                let id = access.acquire_writer();
1509                LifetimeRefMut(self.0.clone(), id)
1510            })
1511    }
1512
1513    /// [`LifetimeLazy::borrow_mut`], awaiting until it succeeds.
1514    pub async fn borrow_mut_async(&self) -> LifetimeRefMut {
1515        loop {
1516            if let Some(lifetime_ref_mut) = self.borrow_mut() {
1517                return lifetime_ref_mut;
1518            }
1519            poll_fn(|cx| {
1520                cx.waker().wake_by_ref();
1521                Poll::<LifetimeRefMut>::Pending
1522            })
1523            .await;
1524        }
1525    }
1526
1527    /// Guards `data` for reading, or returns [`None`] while a write guard is
1528    /// live or the owner is gone.
1529    pub fn read<'a, T: ?Sized>(&'a self, data: &'a T) -> Option<ValueReadAccess<'a, T>> {
1530        let state = self.0.upgrade()?;
1531        let mut access = state.try_lock()?;
1532        if access.state.is_read_accessible() {
1533            access.acquire_read_access();
1534            drop(access);
1535            Some(ValueReadAccess {
1536                lifetime: state,
1537                data,
1538            })
1539        } else {
1540            None
1541        }
1542    }
1543
1544    /// [`LifetimeLazy::read`], awaiting until it succeeds.
1545    pub async fn read_async<'a, T: ?Sized>(&'a self, data: &'a T) -> ValueReadAccess<'a, T> {
1546        loop {
1547            if let Some(access) = self.read(data) {
1548                return access;
1549            }
1550            poll_fn(|cx| {
1551                cx.waker().wake_by_ref();
1552                Poll::<ValueReadAccess<'a, T>>::Pending
1553            })
1554            .await;
1555        }
1556    }
1557
1558    /// [`LifetimeLazy::read`] over a raw pointer.
1559    ///
1560    /// # Safety
1561    ///
1562    /// `data` must stay valid and aligned for as long as the returned guard
1563    /// lives. A null pointer yields [`None`].
1564    pub unsafe fn read_ptr<T: ?Sized>(&'_ self, data: *const T) -> Option<ValueReadAccess<'_, T>> {
1565        // The upgrade must happen before the pointer becomes a reference. The
1566        // owner can already be gone, and a reference into freed memory is
1567        // undefined behavior even when this function then returns `None`.
1568        if data.is_null() {
1569            return None;
1570        }
1571        let state = self.0.upgrade()?;
1572        let mut access = state.try_lock()?;
1573        if access.state.is_read_accessible() {
1574            access.acquire_read_access();
1575            drop(access);
1576            Some(ValueReadAccess {
1577                lifetime: state,
1578                data: unsafe { &*data },
1579            })
1580        } else {
1581            None
1582        }
1583    }
1584
1585    /// [`LifetimeLazy::read_ptr`], awaiting until it succeeds.
1586    ///
1587    /// # Safety
1588    ///
1589    /// Same as [`LifetimeLazy::read_ptr`], and `data` must also stay valid
1590    /// across every await point.
1591    pub async unsafe fn read_ptr_async<'a, T: ?Sized + 'a>(
1592        &'a self,
1593        data: *const T,
1594    ) -> ValueReadAccess<'a, T> {
1595        loop {
1596            if let Some(access) = unsafe { self.read_ptr(data) } {
1597                return access;
1598            }
1599            poll_fn(|cx| {
1600                cx.waker().wake_by_ref();
1601                Poll::<ValueReadAccess<'a, T>>::Pending
1602            })
1603            .await;
1604        }
1605    }
1606
1607    /// Guards `data` for writing, or returns [`None`] while any other access
1608    /// guard is live or the owner is gone.
1609    pub fn write<'a, T: ?Sized>(&'a self, data: &'a mut T) -> Option<ValueWriteAccess<'a, T>> {
1610        let state = self.0.upgrade()?;
1611        let mut access = state.try_lock()?;
1612        if access.state.is_write_accessible() {
1613            access.acquire_write_access();
1614            drop(access);
1615            Some(ValueWriteAccess {
1616                lifetime: state,
1617                data,
1618            })
1619        } else {
1620            None
1621        }
1622    }
1623
1624    /// [`LifetimeLazy::write`], awaiting until it succeeds.
1625    pub async fn write_async<'a, T: ?Sized>(&'a self, data: &'a mut T) -> ValueWriteAccess<'a, T> {
1626        unsafe { self.write_ptr_async(data as *mut T).await }
1627    }
1628
1629    /// [`LifetimeLazy::write`] over a raw pointer.
1630    ///
1631    /// # Safety
1632    ///
1633    /// `data` must stay valid, aligned and unaliased for as long as the
1634    /// returned guard lives. A null pointer yields [`None`].
1635    pub unsafe fn write_ptr<T: ?Sized>(&'_ self, data: *mut T) -> Option<ValueWriteAccess<'_, T>> {
1636        // The upgrade must happen before the pointer becomes a reference. The
1637        // owner can already be gone, and a reference into freed memory is
1638        // undefined behavior even when this function then returns `None`.
1639        if data.is_null() {
1640            return None;
1641        }
1642        let state = self.0.upgrade()?;
1643        let mut access = state.try_lock()?;
1644        if access.state.is_write_accessible() {
1645            access.acquire_write_access();
1646            drop(access);
1647            Some(ValueWriteAccess {
1648                lifetime: state,
1649                data: unsafe { &mut *data },
1650            })
1651        } else {
1652            None
1653        }
1654    }
1655
1656    /// [`LifetimeLazy::write_ptr`], awaiting until it succeeds.
1657    ///
1658    /// # Safety
1659    ///
1660    /// Same as [`LifetimeLazy::write_ptr`], and `data` must also stay valid
1661    /// across every await point.
1662    pub async unsafe fn write_ptr_async<'a, T: ?Sized + 'a>(
1663        &'a self,
1664        data: *mut T,
1665    ) -> ValueWriteAccess<'a, T> {
1666        loop {
1667            if let Some(access) = unsafe { self.write_ptr(data) } {
1668                return access;
1669            }
1670            poll_fn(|cx| {
1671                cx.waker().wake_by_ref();
1672                Poll::<ValueWriteAccess<'a, T>>::Pending
1673            })
1674            .await;
1675        }
1676    }
1677
1678    /// Turns this handle into a write guard over `data`.
1679    ///
1680    /// Gives the handle back unchanged when another access guard is live.
1681    pub fn consume<T: ?Sized>(self, data: &'_ mut T) -> Result<ValueWriteAccess<'_, T>, Self> {
1682        let state = match self.0.upgrade() {
1683            Some(state) => state,
1684            None => return Err(self),
1685        };
1686        let mut access = match state.try_lock() {
1687            Some(access) => access,
1688            None => return Err(self),
1689        };
1690        if access.state.is_write_accessible() {
1691            access.acquire_write_access();
1692            drop(access);
1693            Ok(ValueWriteAccess {
1694                lifetime: state,
1695                data,
1696            })
1697        } else {
1698            Err(self)
1699        }
1700    }
1701
1702    /// Awaits until reading would be allowed, or the owner is gone.
1703    pub async fn wait_for_read_access(&self) {
1704        loop {
1705            let Some(state) = self.0.upgrade() else {
1706                return;
1707            };
1708            if state.is_read_accessible() {
1709                return;
1710            }
1711            poll_fn(|cx| {
1712                cx.waker().wake_by_ref();
1713                Poll::<()>::Pending
1714            })
1715            .await;
1716        }
1717    }
1718
1719    /// Awaits until writing would be allowed, or the owner is gone.
1720    pub async fn wait_for_write_access(&self) {
1721        loop {
1722            let Some(state) = self.0.upgrade() else {
1723                return;
1724            };
1725            if state.is_write_accessible() {
1726                return;
1727            }
1728            poll_fn(|cx| {
1729                cx.waker().wake_by_ref();
1730                Poll::<()>::Pending
1731            })
1732            .await;
1733        }
1734    }
1735}
1736
1737/// Read guard over a value, obtained from a lifetime or one of its handles.
1738///
1739/// Derefs to the value and releases the read claim on drop.
1740pub struct ValueReadAccess<'a, T: 'a + ?Sized> {
1741    lifetime: LifetimeState,
1742    data: &'a T,
1743}
1744
1745impl<T: ?Sized> Drop for ValueReadAccess<'_, T> {
1746    fn drop(&mut self) {
1747        self.lifetime.lock().release_read_access();
1748    }
1749}
1750
1751impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
1752    /// Builds a guard from parts, without going through the state checks.
1753    ///
1754    /// # Safety
1755    ///
1756    /// The read claim on `lifetime` must already be acquired, since dropping
1757    /// this guard releases one. `data` must be the value that `lifetime`
1758    /// guards.
1759    pub unsafe fn new_raw(data: &'a T, lifetime: LifetimeState) -> Self {
1760        Self { lifetime, data }
1761    }
1762}
1763
1764impl<T: ?Sized> Deref for ValueReadAccess<'_, T> {
1765    type Target = T;
1766
1767    fn deref(&self) -> &Self::Target {
1768        self.data
1769    }
1770}
1771
1772impl<'a, T: ?Sized> ValueReadAccess<'a, T> {
1773    /// Narrows the guard down to a part of the value, for example one field.
1774    ///
1775    /// Gives the guard back unchanged when `f` returns [`None`].
1776    pub fn remap<U>(
1777        self,
1778        f: impl FnOnce(&T) -> Option<&U>,
1779    ) -> Result<ValueReadAccess<'a, U>, Self> {
1780        if let Some(data) = f(self.data) {
1781            Ok(ValueReadAccess {
1782                lifetime: self.lifetime.clone(),
1783                data,
1784            })
1785        } else {
1786            Err(self)
1787        }
1788    }
1789}
1790
1791/// Write guard over a value, obtained from a lifetime or one of its
1792/// handles.
1793///
1794/// Derefs to the value mutably and releases the write claim on drop.
1795/// While it is live no other access is allowed.
1796pub struct ValueWriteAccess<'a, T: 'a + ?Sized> {
1797    lifetime: LifetimeState,
1798    data: &'a mut T,
1799}
1800
1801impl<T: ?Sized> Drop for ValueWriteAccess<'_, T> {
1802    fn drop(&mut self) {
1803        self.lifetime.lock().release_write_access();
1804    }
1805}
1806
1807impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
1808    /// Builds a guard from parts, without going through the state checks.
1809    ///
1810    /// # Safety
1811    ///
1812    /// The write claim on `lifetime` must already be acquired, since dropping
1813    /// this guard releases one. `data` must be the value that `lifetime`
1814    /// guards, and must not be aliased.
1815    pub unsafe fn new_raw(data: &'a mut T, lifetime: LifetimeState) -> Self {
1816        Self { lifetime, data }
1817    }
1818}
1819
1820impl<T: ?Sized> Deref for ValueWriteAccess<'_, T> {
1821    type Target = T;
1822
1823    fn deref(&self) -> &Self::Target {
1824        self.data
1825    }
1826}
1827
1828impl<T: ?Sized> DerefMut for ValueWriteAccess<'_, T> {
1829    fn deref_mut(&mut self) -> &mut Self::Target {
1830        self.data
1831    }
1832}
1833
1834impl<'a, T: ?Sized> ValueWriteAccess<'a, T> {
1835    /// Narrows the guard down to a part of the value, for example one field.
1836    ///
1837    /// Gives the guard back unchanged when `f` returns [`None`].
1838    pub fn remap<U>(
1839        self,
1840        f: impl FnOnce(&mut T) -> Option<&mut U>,
1841    ) -> Result<ValueWriteAccess<'a, U>, Self> {
1842        if let Some(data) = f(unsafe { std::mem::transmute::<&mut T, &'a mut T>(&mut *self.data) })
1843        {
1844            Ok(ValueWriteAccess {
1845                lifetime: self.lifetime.clone(),
1846                data,
1847            })
1848        } else {
1849            Err(self)
1850        }
1851    }
1852}
1853
1854/// Read claim held without a reference to the value.
1855///
1856/// Useful for keeping a value readable across code that does not touch it.
1857/// Releases the claim on drop.
1858pub struct ReadLock {
1859    lifetime: LifetimeState,
1860}
1861
1862impl Drop for ReadLock {
1863    fn drop(&mut self) {
1864        self.lifetime.lock().release_read_access();
1865    }
1866}
1867
1868impl ReadLock {
1869    /// Builds a lock from a state, without going through the state checks.
1870    ///
1871    /// # Safety
1872    ///
1873    /// The read claim on `lifetime` must already be acquired, since dropping
1874    /// this lock releases one.
1875    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
1876        Self { lifetime }
1877    }
1878
1879    /// Runs `f` while holding the lock, then releases it.
1880    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
1881        let result = f();
1882        drop(self);
1883        result
1884    }
1885}
1886
1887/// Write claim held without a reference to the value.
1888///
1889/// Blocks every other access until dropped.
1890pub struct WriteLock {
1891    lifetime: LifetimeState,
1892}
1893
1894impl Drop for WriteLock {
1895    fn drop(&mut self) {
1896        self.lifetime.lock().release_write_access();
1897    }
1898}
1899
1900impl WriteLock {
1901    /// Builds a lock from a state, without going through the state checks.
1902    ///
1903    /// # Safety
1904    ///
1905    /// The write claim on `lifetime` must already be acquired, since dropping
1906    /// this lock releases one.
1907    pub unsafe fn new_raw(lifetime: LifetimeState) -> Self {
1908        Self { lifetime }
1909    }
1910
1911    /// Runs `f` while holding the lock, then releases it.
1912    pub fn using<R>(self, f: impl FnOnce() -> R) -> R {
1913        let result = f();
1914        drop(self);
1915        result
1916    }
1917}
1918
1919#[cfg(test)]
1920mod tests {
1921    use super::*;
1922    use std::thread::*;
1923
1924    fn is_async<T: Send + Sync + ?Sized>() {
1925        println!("{} is async!", std::any::type_name::<T>());
1926    }
1927
1928    #[test]
1929    fn test_lifetimes() {
1930        is_async::<Lifetime>();
1931        is_async::<LifetimeRef>();
1932        is_async::<LifetimeRefMut>();
1933        is_async::<LifetimeLazy>();
1934
1935        let mut value = 0usize;
1936        let lifetime_ref = {
1937            let lifetime = Lifetime::default();
1938            assert!(lifetime.state().can_read());
1939            assert!(lifetime.state().can_write(0));
1940            assert!(lifetime.state().is_read_accessible());
1941            assert!(lifetime.state().is_write_accessible());
1942            let lifetime_lazy = lifetime.lazy();
1943            assert!(lifetime_lazy.read(&42).is_some());
1944            assert!(lifetime_lazy.write(&mut 42).is_some());
1945            {
1946                let access = lifetime.read(&value).unwrap();
1947                assert_eq!(*access, value);
1948            }
1949            {
1950                let mut access = lifetime.write(&mut value).unwrap();
1951                *access = 42;
1952                assert_eq!(*access, 42);
1953            }
1954            {
1955                let lifetime_ref = lifetime.borrow().unwrap();
1956                assert!(lifetime.state().can_read());
1957                assert!(!lifetime.state().can_write(0));
1958                assert!(lifetime_ref.exists());
1959                assert!(lifetime_ref.is_owned_by(&lifetime));
1960                assert!(lifetime.borrow().is_some());
1961                assert!(lifetime.borrow_mut().is_none());
1962                assert!(lifetime_lazy.read(&42).is_some());
1963                assert!(lifetime_lazy.write(&mut 42).is_some());
1964                {
1965                    let access = lifetime_ref.read(&value).unwrap();
1966                    assert_eq!(*access, 42);
1967                    assert!(lifetime_lazy.read(&42).is_some());
1968                    assert!(lifetime_lazy.write(&mut 42).is_none());
1969                }
1970                let lifetime_ref2 = lifetime_ref.borrow().unwrap();
1971                {
1972                    let access = lifetime_ref2.read(&value).unwrap();
1973                    assert_eq!(*access, 42);
1974                    assert!(lifetime_lazy.read(&42).is_some());
1975                    assert!(lifetime_lazy.write(&mut 42).is_none());
1976                }
1977            }
1978            {
1979                let lifetime_ref_mut = lifetime.borrow_mut().unwrap();
1980                assert_eq!(lifetime.state().writer_depth(), 1);
1981                assert!(!lifetime.state().can_read());
1982                assert!(!lifetime.state().can_write(0));
1983                assert!(lifetime_ref_mut.exists());
1984                assert!(lifetime_ref_mut.is_owned_by(&lifetime));
1985                assert!(lifetime.borrow().is_none());
1986                assert!(lifetime.borrow_mut().is_none());
1987                assert!(lifetime_lazy.read(&42).is_some());
1988                assert!(lifetime_lazy.write(&mut 42).is_some());
1989                {
1990                    let mut access = lifetime_ref_mut.write(&mut value).unwrap();
1991                    *access = 7;
1992                    assert_eq!(*access, 7);
1993                    assert!(lifetime_lazy.read(&42).is_none());
1994                    assert!(lifetime_lazy.write(&mut 42).is_none());
1995                }
1996                let lifetime_ref_mut2 = lifetime_ref_mut.borrow_mut().unwrap();
1997                assert!(lifetime_lazy.read(&42).is_some());
1998                assert!(lifetime_lazy.write(&mut 42).is_some());
1999                {
2000                    assert_eq!(lifetime.state().writer_depth(), 2);
2001                    assert!(lifetime.borrow().is_none());
2002                    assert!(lifetime_ref_mut.borrow().is_none());
2003                    assert!(lifetime.borrow_mut().is_none());
2004                    assert!(lifetime_ref_mut.borrow_mut().is_none());
2005                    let mut access = lifetime_ref_mut2.write(&mut value).unwrap();
2006                    *access = 42;
2007                    assert_eq!(*access, 42);
2008                    assert!(lifetime.read(&42).is_none());
2009                    assert!(lifetime_ref_mut.read(&42).is_none());
2010                    assert!(lifetime.write(&mut 42).is_none());
2011                    assert!(lifetime_ref_mut.write(&mut 42).is_none());
2012                    assert!(lifetime_lazy.read(&42).is_none());
2013                    assert!(lifetime_lazy.write(&mut 42).is_none());
2014                    assert!(lifetime_lazy.read(&42).is_none());
2015                    assert!(lifetime_lazy.write(&mut 42).is_none());
2016                }
2017            }
2018            assert_eq!(lifetime.state().writer_depth(), 0);
2019            lifetime.borrow().unwrap()
2020        };
2021        assert!(!lifetime_ref.exists());
2022        assert_eq!(value, 42);
2023    }
2024
2025    #[test]
2026    fn test_lifetimes_multithread() {
2027        let lifetime = Lifetime::default();
2028        let lifetime_ref = lifetime.borrow().unwrap();
2029        assert!(lifetime_ref.exists());
2030        assert!(lifetime_ref.is_owned_by(&lifetime));
2031        drop(lifetime);
2032        assert!(!lifetime_ref.exists());
2033        let lifetime = Lifetime::default();
2034        let lifetime = spawn(move || {
2035            let value_ref = lifetime.borrow().unwrap();
2036            assert!(value_ref.exists());
2037            assert!(value_ref.is_owned_by(&lifetime));
2038            lifetime
2039        })
2040        .join()
2041        .unwrap();
2042        assert!(!lifetime_ref.exists());
2043        assert!(!lifetime_ref.is_owned_by(&lifetime));
2044    }
2045
2046    #[test]
2047    fn test_lifetimes_move_invalidation() {
2048        let lifetime = Lifetime::default();
2049        let lifetime_ref = lifetime.borrow().unwrap();
2050        assert_eq!(lifetime_ref.tag(), lifetime.tag());
2051        assert!(lifetime_ref.exists());
2052        let lifetime_ref2 = lifetime_ref;
2053        assert_eq!(lifetime_ref2.tag(), lifetime.tag());
2054        assert!(lifetime_ref2.exists());
2055        let lifetime = Box::new(lifetime);
2056        assert_ne!(lifetime_ref2.tag(), lifetime.tag());
2057        assert!(!lifetime_ref2.exists());
2058        let lifetime = *lifetime;
2059        assert_ne!(lifetime_ref2.tag(), lifetime.tag());
2060        assert!(!lifetime_ref2.exists());
2061    }
2062
2063    #[pollster::test]
2064    async fn test_lifetime_async() {
2065        let mut value = 42usize;
2066        let lifetime = Lifetime::default();
2067        assert_eq!(*lifetime.read_async(&value).await, 42);
2068        {
2069            let lifetime_ref = lifetime.borrow_async().await;
2070            {
2071                let access = lifetime_ref.read_async(&value).await;
2072                assert_eq!(*access, 42);
2073            }
2074        }
2075        {
2076            let lifetime_ref_mut = lifetime.borrow_mut_async().await;
2077            {
2078                let mut access = lifetime_ref_mut.write_async(&mut value).await;
2079                *access = 7;
2080                assert_eq!(*access, 7);
2081            }
2082            assert_eq!(*lifetime.read_async(&value).await, 7);
2083        }
2084        {
2085            let mut access = lifetime.write_async(&mut value).await;
2086            *access = 84;
2087        }
2088        {
2089            let access = lifetime.read_async(&value).await;
2090            assert_eq!(*access, 84);
2091        }
2092    }
2093
2094    #[test]
2095    fn test_lifetime_locks() {
2096        let lifetime = Lifetime::default();
2097        assert!(lifetime.state().is_read_accessible());
2098        assert!(lifetime.state().is_write_accessible());
2099
2100        let read_lock = lifetime.read_lock();
2101        assert!(lifetime.state().is_read_accessible());
2102        assert!(!lifetime.state().is_write_accessible());
2103
2104        drop(read_lock);
2105        assert!(lifetime.state().is_read_accessible());
2106        assert!(lifetime.state().is_write_accessible());
2107
2108        let read_lock = lifetime.read_lock();
2109        assert!(lifetime.state().is_read_accessible());
2110        assert!(!lifetime.state().is_write_accessible());
2111
2112        let read_lock2 = lifetime.read_lock();
2113        assert!(lifetime.state().is_read_accessible());
2114        assert!(!lifetime.state().is_write_accessible());
2115
2116        drop(read_lock);
2117        assert!(lifetime.state().is_read_accessible());
2118        assert!(!lifetime.state().is_write_accessible());
2119
2120        drop(read_lock2);
2121        assert!(lifetime.state().is_read_accessible());
2122        assert!(lifetime.state().is_write_accessible());
2123
2124        let write_lock = lifetime.write_lock();
2125        assert!(!lifetime.state().is_read_accessible());
2126        assert!(!lifetime.state().is_write_accessible());
2127
2128        assert!(lifetime.try_read_lock().is_none());
2129        assert!(lifetime.try_write_lock().is_none());
2130
2131        drop(write_lock);
2132        assert!(lifetime.state().is_read_accessible());
2133        assert!(lifetime.state().is_write_accessible());
2134
2135        let data = ();
2136        let read_access = lifetime.read(&data).unwrap();
2137        assert!(lifetime.state().is_read_accessible());
2138        assert!(!lifetime.state().is_write_accessible());
2139        // the spin lock guards the counter update, not the guard's lifetime
2140        assert!(!lifetime.state().is_locked());
2141
2142        drop(read_access);
2143        assert!(lifetime.try_read_lock().is_some());
2144        assert!(lifetime.try_write_lock().is_some());
2145    }
2146
2147    #[test]
2148    fn test_read_access_guards_coexist() {
2149        let mut value = 42usize;
2150        let lifetime = Lifetime::default();
2151
2152        let first = lifetime.read(&value).unwrap();
2153        let second = lifetime.read(&value).unwrap();
2154        let third = lifetime.read(&value).unwrap();
2155        assert_eq!(*first, 42);
2156        assert_eq!(*second, 42);
2157        assert_eq!(*third, 42);
2158
2159        // no guard holds the spin lock, so nothing below spins or fails early
2160        assert!(!lifetime.state().is_locked());
2161        assert!(lifetime.state().is_read_accessible());
2162        // three readers still keep every writer out
2163        assert!(!lifetime.state().is_write_accessible());
2164        assert!(lifetime.try_write_lock().is_none());
2165        let lock = lifetime.try_read_lock().unwrap();
2166
2167        drop(lock);
2168        drop(third);
2169        drop(second);
2170        assert!(!lifetime.state().is_write_accessible());
2171        drop(first);
2172        assert!(lifetime.state().is_write_accessible());
2173
2174        *lifetime.write(&mut value).unwrap() = 10;
2175        assert_eq!(value, 10);
2176    }
2177
2178    #[test]
2179    fn test_write_access_guard_excludes_readers() {
2180        let mut value = 42usize;
2181        let lifetime = Lifetime::default();
2182
2183        let guard = lifetime.write(&mut value).unwrap();
2184        assert!(!lifetime.state().is_locked());
2185        assert!(!lifetime.state().is_read_accessible());
2186        assert!(lifetime.try_read_lock().is_none());
2187        assert!(lifetime.lazy().read(&0).is_none());
2188
2189        drop(guard);
2190        assert!(lifetime.state().is_read_accessible());
2191        assert!(lifetime.try_read_lock().is_some());
2192    }
2193
2194    #[test]
2195    fn test_null_pointer_leaves_no_access_behind() {
2196        let lifetime = Lifetime::default();
2197
2198        assert!(unsafe { lifetime.read_ptr(std::ptr::null::<usize>()) }.is_none());
2199        assert!(unsafe { lifetime.write_ptr(std::ptr::null_mut::<usize>()) }.is_none());
2200
2201        // a refused guard must not leave its count raised
2202        assert!(lifetime.state().is_read_accessible());
2203        assert!(lifetime.state().is_write_accessible());
2204        assert!(lifetime.try_write_lock().is_some());
2205    }
2206
2207    /// A dead owner must be detected before the pointer becomes a reference.
2208    /// The other order builds a reference into freed memory, which is
2209    /// undefined behavior even though the guard is then refused.
2210    #[test]
2211    fn test_dead_owner_never_dereferences_the_pointer() {
2212        let data = Box::into_raw(Box::new(42usize));
2213        let shared = Lifetime::default();
2214        let exclusive = Lifetime::default();
2215        let unclaimed = Lifetime::default();
2216        let value_ref = shared.borrow().unwrap();
2217        let value_ref_mut = exclusive.borrow_mut().unwrap();
2218        let value_lazy = unclaimed.lazy();
2219
2220        drop((shared, exclusive, unclaimed));
2221        unsafe { drop(Box::from_raw(data)) };
2222
2223        assert!(unsafe { value_ref.read_ptr(data) }.is_none());
2224        assert!(unsafe { value_ref_mut.read_ptr(data) }.is_none());
2225        assert!(unsafe { value_ref_mut.write_ptr(data) }.is_none());
2226        assert!(unsafe { value_lazy.read_ptr(data) }.is_none());
2227        assert!(unsafe { value_lazy.write_ptr(data) }.is_none());
2228    }
2229
2230    #[test]
2231    fn test_read_access_guards_across_threads() {
2232        let lifetime = Arc::new(Lifetime::default());
2233        let value = Arc::new(7usize);
2234
2235        let threads = (0..8)
2236            .map(|_| {
2237                let lifetime = lifetime.clone();
2238                let value = value.clone();
2239                spawn(move || {
2240                    let mut taken = 0usize;
2241                    for _ in 0..1000 {
2242                        if let Some(access) = lifetime.read(value.as_ref()) {
2243                            assert_eq!(*access, 7);
2244                            taken += 1;
2245                        }
2246                    }
2247                    taken
2248                })
2249            })
2250            .collect::<Vec<_>>();
2251        let total = threads
2252            .into_iter()
2253            .map(|thread| thread.join().unwrap())
2254            .sum::<usize>();
2255        assert!(total > 0);
2256
2257        // every guard is gone, so the counter has to be back at zero
2258        assert!(lifetime.state().is_write_accessible());
2259    }
2260}