hv_cell/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! A `no_std` port of the `atomic_refcell` crate, with added functionality for `Arc`-wrapped
6//! `AtomicRefCell`s.
7//!
8//! Implements a container type providing RefCell-like semantics for objects
9//! shared across threads.
10//!
11//! RwLock is traditionally considered to be the |Sync| analogue of RefCell.
12//! However, for consumers that can guarantee that they will never mutably
13//! borrow the contents concurrently with immutable borrows, an RwLock is
14//! overkill, and has key disadvantages:
15//! * Performance: Even the fastest existing implementation of RwLock (that of
16//!   parking_lot) performs at least two atomic operations during immutable
17//!   borrows. This makes mutable borrows significantly cheaper than immutable
18//!   borrows, leading to weird incentives when writing performance-critical
19//!   code.
20//! * Features: Implementing AtomicRefCell on top of RwLock makes it impossible
21//!   to implement useful things like AtomicRef{,Mut}::map.
22//!
23//! As such, we re-implement RefCell semantics from scratch with a single atomic
24//! reference count. The primary complication of this scheme relates to keeping
25//! things in a consistent state when one thread performs an illegal borrow and
26//! panics. Since an AtomicRefCell can be accessed by multiple threads, and since
27//! panics are recoverable, we need to ensure that an illegal (panicking) access by
28//! one thread does not lead to undefined behavior on other, still-running threads.
29//!
30//! So we represent things as follows:
31//! * Any value with the high bit set (so half the total refcount space) indicates
32//!   a mutable borrow.
33//! * Mutable borrows perform an atomic compare-and-swap, swapping in the high bit
34//!   if the current value is zero. If the current value is non-zero, the thread
35//!   panics and the value is left undisturbed.
36//! * Immutable borrows perform an atomic increment. If the new value has the high
37//!   bit set, the thread panics. The incremented refcount is left as-is, since it
38//!   still represents a valid mutable borrow. When the mutable borrow is released,
39//!   the refcount is set unconditionally to zero, clearing any stray increments by
40//!   panicked threads.
41//!
42//! There are a few additional purely-academic complications to handle overflow,
43//! which are documented in the implementation.
44//!
45//! The rest of this module is mostly derived by copy-pasting the implementation of
46//! RefCell and fixing things up as appropriate. Certain non-threadsafe methods
47//! have been removed. We segment the concurrency logic from the rest of the code to
48//! keep the tricky parts small and easy to audit.
49
50#![no_std]
51#![feature(generic_associated_types)]
52#![allow(unsafe_code)]
53#![deny(missing_docs)]
54
55extern crate alloc;
56
57use alloc::sync::Arc;
58use core::cmp;
59use core::fmt;
60use core::fmt::{Debug, Display};
61use core::ops::{Deref, DerefMut};
62use core::sync::atomic;
63use core::sync::atomic::AtomicUsize;
64use core::{cell::UnsafeCell, convert::Infallible};
65use hv_guarded_borrow::{
66    NonBlockingGuardedBorrow, NonBlockingGuardedBorrowMut, NonBlockingGuardedMutBorrowMut,
67};
68
69#[cfg(feature = "track-leases")]
70use hv_lease_tracker::{Lease, LeaseTracker};
71
72/// A threadsafe analogue to RefCell but where the borrows are considered strong references to the
73/// inner `Arc`'d value.
74pub struct ArcCell<T: ?Sized> {
75    inner: Arc<AtomicRefCell<T>>,
76}
77
78impl<T> ArcCell<T> {
79    /// Wrap a value in an `ArcCell`.
80    #[inline]
81    pub fn new(value: T) -> Self {
82        Self {
83            inner: Arc::new(AtomicRefCell::new(value)),
84        }
85    }
86}
87
88impl<T: ?Sized> ArcCell<T> {
89    /// Immutably borrows the wrapped value.
90    #[inline]
91    pub fn borrow(&self) -> ArcRef<T> {
92        match AtomicBorrowRef::try_new(&self.inner.borrows) {
93            Ok(borrow) => ArcRef {
94                value: unsafe { &*(*self.inner).value.get() },
95                guard: ArcRefGuard {
96                    borrow,
97                    cell: self.inner.clone(),
98                },
99
100                #[cfg(feature = "track-leases")]
101                lease: self.inner.lease_tracker.lease_at_caller(Some("immutable")),
102            },
103            Err(s) => panic!("{}", s),
104        }
105    }
106
107    /// Attempts to immutably borrow the wrapped value, but instead of panicking
108    /// on a failed borrow, returns `Err`.
109    #[inline]
110    pub fn try_borrow(&self) -> Result<ArcRef<T>, BorrowError> {
111        match AtomicBorrowRef::try_new(&self.inner.borrows) {
112            Ok(borrow) => Ok(ArcRef {
113                value: unsafe { &*self.inner.value.get() },
114                guard: ArcRefGuard {
115                    borrow,
116                    cell: self.inner.clone(),
117                },
118
119                #[cfg(feature = "track-leases")]
120                lease: self.inner.lease_tracker.lease_at_caller(Some("immutable")),
121            }),
122            Err(_) => Err(BorrowError { _private: () }),
123        }
124    }
125
126    /// Mutably borrows the wrapped value.
127    #[inline]
128    pub fn borrow_mut(&self) -> ArcRefMut<T> {
129        match AtomicBorrowRefMut::try_new(&self.inner.borrows) {
130            Ok(borrow) => ArcRefMut {
131                value: unsafe { &mut *self.inner.value.get() },
132                guard: ArcRefMutGuard {
133                    cell: self.inner.clone(),
134                    borrow,
135                },
136
137                #[cfg(feature = "track-leases")]
138                lease: self.inner.lease_tracker.lease_at_caller(Some("mutable")),
139            },
140            Err(s) => panic!("{}", s),
141        }
142    }
143
144    /// Attempts to mutably borrow the wrapped value, but instead of panicking
145    /// on a failed borrow, returns `Err`.
146    #[inline]
147    pub fn try_borrow_mut(&self) -> Result<ArcRefMut<T>, BorrowMutError> {
148        match AtomicBorrowRefMut::try_new(&self.inner.borrows) {
149            Ok(borrow) => Ok(ArcRefMut {
150                value: unsafe { &mut *self.inner.value.get() },
151                guard: ArcRefMutGuard {
152                    cell: self.inner.clone(),
153                    borrow,
154                },
155
156                #[cfg(feature = "track-leases")]
157                lease: self.inner.lease_tracker.lease_at_caller(Some("mutable")),
158            }),
159            Err(_) => Err(BorrowMutError { _private: () }),
160        }
161    }
162
163    /// Get a reference to the [`Arc`]'d [`AtomicRefCell`] which is managed by this type.
164    #[inline]
165    pub fn as_inner(&self) -> &Arc<AtomicRefCell<T>> {
166        &self.inner
167    }
168
169    /// Consume the `ArcCell` and return the inner [`Arc`]'d [`AtomicRefCell`] which is managed by
170    /// this type.
171    #[inline]
172    pub fn into_inner(self) -> Arc<AtomicRefCell<T>> {
173        self.inner
174    }
175
176    /// Construct an `ArcCell` from an [`Arc`]'d [`AtomicRefCell`].
177    #[inline]
178    pub fn from_inner(inner: Arc<AtomicRefCell<T>>) -> Self {
179        Self { inner }
180    }
181}
182
183/// A threadsafe analogue to RefCell.
184pub struct AtomicRefCell<T: ?Sized> {
185    #[cfg(feature = "track-leases")]
186    lease_tracker: LeaseTracker,
187
188    borrows: AtomicUsize,
189    value: UnsafeCell<T>,
190}
191
192/// An error returned by [`AtomicRefCell::try_borrow`](struct.AtomicRefCell.html#method.try_borrow).
193pub struct BorrowError {
194    _private: (),
195}
196
197impl Debug for BorrowError {
198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199        f.debug_struct("BorrowError").finish()
200    }
201}
202
203impl Display for BorrowError {
204    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205        Display::fmt("already mutably borrowed", f)
206    }
207}
208
209/// An error returned by [`AtomicRefCell::try_borrow_mut`](struct.AtomicRefCell.html#method.try_borrow_mut).
210pub struct BorrowMutError {
211    _private: (),
212}
213
214impl Debug for BorrowMutError {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        f.debug_struct("BorrowMutError").finish()
217    }
218}
219
220impl Display for BorrowMutError {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        Display::fmt("already borrowed", f)
223    }
224}
225
226impl<T> AtomicRefCell<T> {
227    /// Creates a new `AtomicRefCell` containing `value`.
228    #[inline]
229    pub fn new(value: T) -> AtomicRefCell<T> {
230        AtomicRefCell {
231            #[cfg(feature = "track-leases")]
232            lease_tracker: LeaseTracker::new(),
233
234            borrows: AtomicUsize::new(0),
235            value: UnsafeCell::new(value),
236        }
237    }
238
239    /// Consumes the `AtomicRefCell`, returning the wrapped value.
240    #[inline]
241    pub fn into_inner(self) -> T {
242        debug_assert!(self.borrows.load(atomic::Ordering::Acquire) == 0);
243        self.value.into_inner()
244    }
245}
246
247impl<T: ?Sized> AtomicRefCell<T> {
248    /// Immutably borrows the wrapped value.
249    #[inline]
250    #[track_caller]
251    pub fn borrow(&self) -> AtomicRef<T> {
252        match AtomicBorrowRef::try_new(&self.borrows) {
253            Ok(borrow) => AtomicRef {
254                value: unsafe { &*self.value.get() },
255                guard: AtomicRefGuard {
256                    count: &self.borrows,
257                    borrow,
258                },
259
260                #[cfg(feature = "track-leases")]
261                lease: self.lease_tracker.lease_at_caller(Some("immutable")),
262            },
263            Err(s) => panic!("{}", s),
264        }
265    }
266
267    /// Attempts to immutably borrow the wrapped value, but instead of panicking
268    /// on a failed borrow, returns `Err`.
269    #[inline]
270    #[track_caller]
271    pub fn try_borrow(&self) -> Result<AtomicRef<T>, BorrowError> {
272        match AtomicBorrowRef::try_new(&self.borrows) {
273            Ok(borrow) => Ok(AtomicRef {
274                value: unsafe { &*self.value.get() },
275                guard: AtomicRefGuard {
276                    count: &self.borrows,
277                    borrow,
278                },
279
280                #[cfg(feature = "track-leases")]
281                lease: self.lease_tracker.lease_at_caller(Some("immutable")),
282            }),
283            Err(_) => Err(BorrowError { _private: () }),
284        }
285    }
286
287    /// Mutably borrows the wrapped value.
288    #[inline]
289    #[track_caller]
290    pub fn borrow_mut(&self) -> AtomicRefMut<T> {
291        match AtomicBorrowRefMut::try_new(&self.borrows) {
292            Ok(borrow) => AtomicRefMut {
293                value: unsafe { &mut *self.value.get() },
294                guard: AtomicRefMutGuard {
295                    count: &self.borrows,
296                    borrow,
297                },
298
299                #[cfg(feature = "track-leases")]
300                lease: self.lease_tracker.lease_at_caller(Some("mutable")),
301            },
302            Err(s) => panic!("{}", s),
303        }
304    }
305
306    /// Attempts to mutably borrow the wrapped value, but instead of panicking
307    /// on a failed borrow, returns `Err`.
308    #[inline]
309    #[track_caller]
310    pub fn try_borrow_mut(&self) -> Result<AtomicRefMut<T>, BorrowMutError> {
311        match AtomicBorrowRefMut::try_new(&self.borrows) {
312            Ok(borrow) => Ok(AtomicRefMut {
313                value: unsafe { &mut *self.value.get() },
314                guard: AtomicRefMutGuard {
315                    count: &self.borrows,
316                    borrow,
317                },
318
319                #[cfg(feature = "track-leases")]
320                lease: self.lease_tracker.lease_at_caller(Some("mutable")),
321            }),
322            Err(_) => Err(BorrowMutError { _private: () }),
323        }
324    }
325
326    /// Returns a raw pointer to the underlying data in this cell.
327    ///
328    /// External synchronization is needed to avoid data races when dereferencing
329    /// the pointer.
330    #[inline]
331    pub fn as_ptr(&self) -> *mut T {
332        self.value.get()
333    }
334
335    /// Returns a mutable reference to the wrapped value.
336    ///
337    /// No runtime checks take place (unless debug assertions are enabled)
338    /// because this call borrows `AtomicRefCell` mutably at compile-time.
339    #[inline]
340    pub fn get_mut(&mut self) -> &mut T {
341        debug_assert!(self.borrows.load(atomic::Ordering::Acquire) == 0);
342        unsafe { &mut *self.value.get() }
343    }
344}
345
346//
347// Core synchronization logic. Keep this section small and easy to audit.
348//
349
350const HIGH_BIT: usize = !(::core::usize::MAX >> 1);
351const MAX_FAILED_BORROWS: usize = HIGH_BIT + (HIGH_BIT >> 1);
352
353struct AtomicBorrowRef;
354
355impl AtomicBorrowRef {
356    #[inline]
357    fn try_new(borrow: &AtomicUsize) -> Result<Self, &'static str> {
358        let new = borrow.fetch_add(1, atomic::Ordering::Acquire) + 1;
359        if new & HIGH_BIT != 0 {
360            // If the new count has the high bit set, that almost certainly
361            // means there's an pre-existing mutable borrow. In that case,
362            // we simply leave the increment as a benign side-effect and
363            // return `Err`. Once the mutable borrow is released, the
364            // count will be reset to zero unconditionally.
365            //
366            // The overflow check here ensures that an unbounded number of
367            // immutable borrows during the scope of one mutable borrow
368            // will soundly trigger a panic (or abort) rather than UB.
369            Self::check_overflow(borrow, new);
370            Err("already mutably borrowed")
371        } else {
372            Ok(AtomicBorrowRef)
373        }
374    }
375
376    #[cold]
377    #[inline(never)]
378    fn check_overflow(borrow: &AtomicUsize, new: usize) {
379        if new == HIGH_BIT {
380            // We overflowed into the reserved upper half of the refcount
381            // space. Before panicking, decrement the refcount to leave things
382            // in a consistent immutable-borrow state.
383            //
384            // This can basically only happen if somebody forget()s AtomicRefs
385            // in a tight loop.
386            borrow.fetch_sub(1, atomic::Ordering::Release);
387            panic!("too many immutable borrows");
388        } else if new >= MAX_FAILED_BORROWS {
389            // During the mutable borrow, an absurd number of threads have
390            // attempted to increment the refcount with immutable borrows.
391            // To avoid hypothetically wrapping the refcount, we abort the
392            // process once a certain threshold is reached.
393            //
394            // This requires billions of borrows to fail during the scope of
395            // one mutable borrow, and so is very unlikely to happen in a real
396            // program.
397            //
398            // To avoid a potential unsound state after overflowing, we make
399            // sure the entire process aborts.
400            //
401            // Right now, there's no stable way to do that without `std`:
402            // https://github.com/rust-lang/rust/issues/67952
403            // As a workaround, we cause an abort by making this thread panic
404            // during the unwinding of another panic.
405            //
406            // On platforms where the panic strategy is already 'abort', the
407            // ForceAbort object here has no effect, as the program already
408            // panics before it is dropped.
409            struct ForceAbort;
410            impl Drop for ForceAbort {
411                fn drop(&mut self) {
412                    panic!("Aborting to avoid unsound state of AtomicRefCell");
413                }
414            }
415            let _abort = ForceAbort;
416            panic!("Too many failed borrows");
417        }
418    }
419
420    #[inline]
421    fn release(&self, borrow: &AtomicUsize) {
422        let old = borrow.fetch_sub(1, atomic::Ordering::Release);
423        // This assertion is technically incorrect in the case where another
424        // thread hits the hypothetical overflow case, since we might observe
425        // the refcount before it fixes it up (and panics). But that never will
426        // never happen in a real program, and this is a debug_assert! anyway.
427        debug_assert!(old & HIGH_BIT == 0);
428    }
429}
430
431struct AtomicBorrowRefMut;
432
433impl AtomicBorrowRefMut {
434    #[inline]
435    fn try_new(borrow: &AtomicUsize) -> Result<Self, &'static str> {
436        // Use compare-and-swap to avoid corrupting the immutable borrow count
437        // on illegal mutable borrows.
438        let old = match borrow.compare_exchange(
439            0,
440            HIGH_BIT,
441            atomic::Ordering::Acquire,
442            atomic::Ordering::Relaxed,
443        ) {
444            Ok(x) => x,
445            Err(x) => x,
446        };
447
448        if old == 0 {
449            Ok(AtomicBorrowRefMut)
450        } else if old & HIGH_BIT == 0 {
451            Err("already immutably borrowed")
452        } else {
453            Err("already mutably borrowed")
454        }
455    }
456
457    #[inline]
458    fn release(&self, borrow: &AtomicUsize) {
459        borrow.store(0, atomic::Ordering::Release);
460    }
461}
462
463unsafe impl<T: ?Sized + Send> Send for AtomicRefCell<T> {}
464unsafe impl<T: ?Sized + Send + Sync> Sync for AtomicRefCell<T> {}
465
466//
467// End of core synchronization logic. No tricky thread stuff allowed below
468// this point.
469//
470
471impl<T: Clone> Clone for AtomicRefCell<T> {
472    #[inline]
473    fn clone(&self) -> AtomicRefCell<T> {
474        AtomicRefCell::new((*self.borrow()).clone())
475    }
476}
477
478impl<T: Default> Default for AtomicRefCell<T> {
479    #[inline]
480    fn default() -> AtomicRefCell<T> {
481        AtomicRefCell::new(Default::default())
482    }
483}
484
485impl<T: ?Sized + PartialEq> PartialEq for AtomicRefCell<T> {
486    #[inline]
487    fn eq(&self, other: &AtomicRefCell<T>) -> bool {
488        *self.borrow() == *other.borrow()
489    }
490}
491
492impl<T: ?Sized + Eq> Eq for AtomicRefCell<T> {}
493
494impl<T: ?Sized + PartialOrd> PartialOrd for AtomicRefCell<T> {
495    #[inline]
496    fn partial_cmp(&self, other: &AtomicRefCell<T>) -> Option<cmp::Ordering> {
497        self.borrow().partial_cmp(&*other.borrow())
498    }
499}
500
501impl<T: ?Sized + Ord> Ord for AtomicRefCell<T> {
502    #[inline]
503    fn cmp(&self, other: &AtomicRefCell<T>) -> cmp::Ordering {
504        self.borrow().cmp(&*other.borrow())
505    }
506}
507
508impl<T> From<T> for AtomicRefCell<T> {
509    fn from(t: T) -> AtomicRefCell<T> {
510        AtomicRefCell::new(t)
511    }
512}
513
514impl<T: ?Sized> Clone for ArcCell<T> {
515    fn clone(&self) -> Self {
516        Self {
517            inner: self.inner.clone(),
518        }
519    }
520}
521
522impl<T: Default> Default for ArcCell<T> {
523    #[inline]
524    fn default() -> ArcCell<T> {
525        ArcCell::new(Default::default())
526    }
527}
528
529impl<T: ?Sized + PartialEq> PartialEq for ArcCell<T> {
530    #[inline]
531    fn eq(&self, other: &ArcCell<T>) -> bool {
532        *self.borrow() == *other.borrow()
533    }
534}
535
536impl<T: ?Sized + Eq> Eq for ArcCell<T> {}
537
538impl<T: ?Sized + PartialOrd> PartialOrd for ArcCell<T> {
539    #[inline]
540    fn partial_cmp(&self, other: &ArcCell<T>) -> Option<cmp::Ordering> {
541        self.borrow().partial_cmp(&*other.borrow())
542    }
543}
544
545impl<T: ?Sized + Ord> Ord for ArcCell<T> {
546    #[inline]
547    fn cmp(&self, other: &ArcCell<T>) -> cmp::Ordering {
548        self.borrow().cmp(&*other.borrow())
549    }
550}
551
552impl<T> From<T> for ArcCell<T> {
553    fn from(t: T) -> ArcCell<T> {
554        ArcCell::new(t)
555    }
556}
557
558struct AtomicRefGuard<'b> {
559    count: &'b AtomicUsize,
560    borrow: AtomicBorrowRef,
561}
562
563impl<'b> Drop for AtomicRefGuard<'b> {
564    fn drop(&mut self) {
565        self.borrow.release(self.count);
566    }
567}
568
569impl<'b> Clone for AtomicRefGuard<'b> {
570    #[inline]
571    #[track_caller]
572    fn clone(&self) -> Self {
573        Self {
574            count: self.count,
575            borrow: AtomicBorrowRef::try_new(self.count).unwrap(),
576        }
577    }
578}
579
580/// A wrapper type for an immutably borrowed value from an `AtomicRefCell<T>`.
581pub struct AtomicRef<'b, T: ?Sized + 'b> {
582    value: &'b T,
583    guard: AtomicRefGuard<'b>,
584
585    #[cfg(feature = "track-leases")]
586    lease: Lease,
587}
588
589impl<'b, T: ?Sized> Deref for AtomicRef<'b, T> {
590    type Target = T;
591
592    #[inline]
593    fn deref(&self) -> &T {
594        self.value
595    }
596}
597
598impl<'b, T: ?Sized> Clone for AtomicRef<'b, T> {
599    #[inline]
600    #[track_caller]
601    fn clone(&self) -> AtomicRef<'b, T> {
602        AtomicRef {
603            value: self.value,
604            guard: self.guard.clone(),
605
606            #[cfg(feature = "track-leases")]
607            lease: self.lease.tracker().lease_at_caller(Some("immutable")),
608        }
609    }
610}
611
612impl<'b, T: ?Sized> AtomicRef<'b, T> {
613    /// Make a new `AtomicRef` for a component of the borrowed data.
614    #[inline]
615    pub fn map<U: ?Sized, F>(orig: AtomicRef<'b, T>, f: F) -> AtomicRef<'b, U>
616    where
617        F: FnOnce(&T) -> &U,
618    {
619        AtomicRef {
620            value: f(orig.value),
621            guard: orig.guard,
622
623            #[cfg(feature = "track-leases")]
624            lease: orig.lease,
625        }
626    }
627
628    /// Make a new `AtomicRef` for an optional component of the borrowed data.
629    #[inline]
630    pub fn filter_map<U: ?Sized, F>(orig: AtomicRef<'b, T>, f: F) -> Option<AtomicRef<'b, U>>
631    where
632        F: FnOnce(&T) -> Option<&U>,
633    {
634        Some(AtomicRef {
635            value: f(orig.value)?,
636            guard: orig.guard,
637
638            #[cfg(feature = "track-leases")]
639            lease: orig.lease,
640        })
641    }
642}
643
644struct AtomicRefMutGuard<'b> {
645    count: &'b AtomicUsize,
646    borrow: AtomicBorrowRefMut,
647}
648
649impl<'b> Drop for AtomicRefMutGuard<'b> {
650    fn drop(&mut self) {
651        self.borrow.release(self.count);
652    }
653}
654
655/// A wrapper type for a mutably borrowed value from an `AtomicRefCell<T>`.
656pub struct AtomicRefMut<'b, T: ?Sized + 'b> {
657    value: &'b mut T,
658    guard: AtomicRefMutGuard<'b>,
659
660    #[cfg(feature = "track-leases")]
661    lease: Lease,
662}
663
664impl<'b, T: ?Sized> AtomicRefMut<'b, T> {
665    /// Make a new `AtomicRefMut` for a component of the borrowed data, e.g. an enum
666    /// variant.
667    #[inline]
668    pub fn map<U: ?Sized, F>(orig: AtomicRefMut<'b, T>, f: F) -> AtomicRefMut<'b, U>
669    where
670        F: FnOnce(&mut T) -> &mut U,
671    {
672        AtomicRefMut {
673            value: f(orig.value),
674            guard: orig.guard,
675
676            #[cfg(feature = "track-leases")]
677            lease: orig.lease,
678        }
679    }
680
681    /// Make a new `AtomicRefMut` for an optional component of the borrowed data.
682    #[inline]
683    pub fn filter_map<U: ?Sized, F>(orig: AtomicRefMut<'b, T>, f: F) -> Option<AtomicRefMut<'b, U>>
684    where
685        F: FnOnce(&mut T) -> Option<&mut U>,
686    {
687        Some(AtomicRefMut {
688            value: f(orig.value)?,
689            guard: orig.guard,
690
691            #[cfg(feature = "track-leases")]
692            lease: orig.lease,
693        })
694    }
695}
696
697impl<'b, T: ?Sized> Deref for AtomicRefMut<'b, T> {
698    type Target = T;
699
700    #[inline]
701    fn deref(&self) -> &T {
702        self.value
703    }
704}
705
706impl<'b, T: ?Sized> DerefMut for AtomicRefMut<'b, T> {
707    #[inline]
708    fn deref_mut(&mut self) -> &mut T {
709        self.value
710    }
711}
712
713impl<'b, T: ?Sized + Debug + 'b> Debug for AtomicRef<'b, T> {
714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
715        self.value.fmt(f)
716    }
717}
718
719impl<'b, T: ?Sized + Debug + 'b> Debug for AtomicRefMut<'b, T> {
720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
721        self.value.fmt(f)
722    }
723}
724
725struct ArcRefGuard<C: ?Sized> {
726    cell: Arc<AtomicRefCell<C>>,
727    borrow: AtomicBorrowRef,
728}
729
730impl<C: ?Sized> Drop for ArcRefGuard<C> {
731    fn drop(&mut self) {
732        self.borrow.release(&self.cell.borrows);
733    }
734}
735
736/// A wrapper type for an immutably borrowed value from an `ArcRefCell<T>`.
737pub struct ArcRef<T: ?Sized, C: ?Sized = T> {
738    value: *const T,
739    guard: ArcRefGuard<C>,
740
741    #[cfg(feature = "track-leases")]
742    lease: Lease,
743}
744
745unsafe impl<T: Send + Sync, C: ?Sized + Send + Sync> Send for ArcRef<T, C> {}
746unsafe impl<T: Send + Sync, C: ?Sized> Sync for ArcRef<T, C> {}
747
748impl<T: ?Sized, C: ?Sized> Deref for ArcRef<T, C> {
749    type Target = T;
750
751    #[inline]
752    fn deref(&self) -> &T {
753        unsafe { &*self.value }
754    }
755}
756
757impl<T: ?Sized, C: ?Sized> Clone for ArcRef<T, C> {
758    fn clone(&self) -> Self {
759        ArcRef {
760            value: self.value,
761            guard: ArcRefGuard {
762                cell: self.guard.cell.clone(),
763                borrow: AtomicBorrowRef::try_new(&self.guard.cell.borrows).unwrap(),
764            },
765
766            #[cfg(feature = "track-leases")]
767            lease: self.lease.tracker().lease_at_caller(Some("immutable")),
768        }
769    }
770}
771
772impl<T: ?Sized, C: ?Sized> ArcRef<T, C> {
773    /// Make a new `ArcRef` for a component of the borrowed data.
774    #[inline]
775    pub fn map<U: ?Sized, F>(orig: ArcRef<T, C>, f: F) -> ArcRef<U, C>
776    where
777        F: FnOnce(&T) -> &U,
778    {
779        ArcRef {
780            value: f(unsafe { &*orig.value }),
781            guard: orig.guard,
782
783            #[cfg(feature = "track-leases")]
784            lease: orig.lease,
785        }
786    }
787
788    /// Make a new `ArcRef` for an optional component of the borrowed data.
789    #[inline]
790    pub fn filter_map<U: ?Sized, F>(orig: ArcRef<T, C>, f: F) -> Option<ArcRef<U, C>>
791    where
792        F: FnOnce(&T) -> Option<&U>,
793    {
794        Some(ArcRef {
795            value: f(unsafe { &*orig.value })?,
796            guard: orig.guard,
797
798            #[cfg(feature = "track-leases")]
799            lease: orig.lease,
800        })
801    }
802}
803
804struct ArcRefMutGuard<C: ?Sized> {
805    cell: Arc<AtomicRefCell<C>>,
806    borrow: AtomicBorrowRefMut,
807}
808
809impl<C: ?Sized> Drop for ArcRefMutGuard<C> {
810    fn drop(&mut self) {
811        self.borrow.release(&self.cell.borrows);
812    }
813}
814
815/// A wrapper type for a mutably borrowed value from an `ArcRefCell<T>`.
816pub struct ArcRefMut<T: ?Sized, C: ?Sized = T> {
817    value: *mut T,
818    guard: ArcRefMutGuard<C>,
819
820    #[cfg(feature = "track-leases")]
821    lease: Lease,
822}
823
824unsafe impl<T: Send + Sync, C: ?Sized + Send + Sync> Send for ArcRefMut<T, C> {}
825unsafe impl<T: Send + Sync, C: ?Sized> Sync for ArcRefMut<T, C> {}
826
827impl<T: ?Sized, C: ?Sized> ArcRefMut<T, C> {
828    /// Make a new `ArcRefMut` for a component of the borrowed data.
829    #[inline]
830    pub fn map<U: ?Sized, F>(orig: ArcRefMut<T, C>, f: F) -> ArcRefMut<U, C>
831    where
832        F: FnOnce(&mut T) -> &mut U,
833    {
834        ArcRefMut {
835            value: f(unsafe { &mut *orig.value }),
836            guard: orig.guard,
837
838            #[cfg(feature = "track-leases")]
839            lease: orig.lease,
840        }
841    }
842
843    /// Make a new `ArcRef` for an optional component of the borrowed data.
844    #[inline]
845    pub fn filter_map<U: ?Sized, F>(orig: ArcRefMut<T, C>, f: F) -> Option<ArcRefMut<U, C>>
846    where
847        F: FnOnce(&mut T) -> Option<&mut U>,
848    {
849        Some(ArcRefMut {
850            value: f(unsafe { &mut *orig.value })?,
851            guard: orig.guard,
852
853            #[cfg(feature = "track-leases")]
854            lease: orig.lease,
855        })
856    }
857}
858
859impl<T: ?Sized, C: ?Sized> Deref for ArcRefMut<T, C> {
860    type Target = T;
861
862    #[inline]
863    fn deref(&self) -> &T {
864        unsafe { &*self.value }
865    }
866}
867
868impl<T: ?Sized, C: ?Sized> DerefMut for ArcRefMut<T, C> {
869    #[inline]
870    fn deref_mut(&mut self) -> &mut T {
871        unsafe { &mut *self.value }
872    }
873}
874
875impl<T: ?Sized + Debug, C: ?Sized> Debug for ArcRef<T, C> {
876    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
877        self.value.fmt(f)
878    }
879}
880
881impl<T: ?Sized + Debug, C: ?Sized> Debug for ArcRefMut<T, C> {
882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
883        self.value.fmt(f)
884    }
885}
886
887impl<T: ?Sized + Debug> Debug for ArcCell<T> {
888    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889        write!(f, "ArcCell {{ ... }}")
890    }
891}
892
893impl<T: ?Sized + Debug> Debug for AtomicRefCell<T> {
894    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
895        write!(f, "AtomicRefCell {{ ... }}")
896    }
897}
898
899impl<T: ?Sized> NonBlockingGuardedBorrow<T> for AtomicRefCell<T> {
900    type Guard<'a>
901    where
902        T: 'a,
903    = AtomicRef<'a, T>;
904    type BorrowError<'a>
905    where
906        T: 'a,
907    = BorrowError;
908
909    fn try_nonblocking_guarded_borrow(&self) -> Result<Self::Guard<'_>, Self::BorrowError<'_>> {
910        self.try_borrow()
911    }
912}
913
914impl<T: ?Sized> NonBlockingGuardedBorrowMut<T> for AtomicRefCell<T> {
915    type GuardMut<'a>
916    where
917        T: 'a,
918    = AtomicRefMut<'a, T>;
919    type BorrowMutError<'a>
920    where
921        T: 'a,
922    = BorrowMutError;
923
924    fn try_nonblocking_guarded_borrow_mut(
925        &self,
926    ) -> Result<Self::GuardMut<'_>, Self::BorrowMutError<'_>> {
927        self.try_borrow_mut()
928    }
929}
930
931impl<T: ?Sized> NonBlockingGuardedMutBorrowMut<T> for AtomicRefCell<T> {
932    type MutGuardMut<'a>
933    where
934        T: 'a,
935    = &'a mut T;
936    type MutBorrowMutError<'a>
937    where
938        T: 'a,
939    = Infallible;
940
941    fn try_nonblocking_guarded_mut_borrow_mut(
942        &mut self,
943    ) -> Result<Self::MutGuardMut<'_>, Self::MutBorrowMutError<'_>> {
944        Ok(self.get_mut())
945    }
946}
947
948impl<T: ?Sized> NonBlockingGuardedBorrow<T> for ArcCell<T> {
949    type Guard<'a>
950    where
951        T: 'a,
952    = AtomicRef<'a, T>;
953    type BorrowError<'a>
954    where
955        T: 'a,
956    = BorrowError;
957
958    fn try_nonblocking_guarded_borrow(&self) -> Result<Self::Guard<'_>, Self::BorrowError<'_>> {
959        self.as_inner().try_borrow()
960    }
961}
962
963impl<T: ?Sized> NonBlockingGuardedBorrowMut<T> for ArcCell<T> {
964    type GuardMut<'a>
965    where
966        T: 'a,
967    = AtomicRefMut<'a, T>;
968    type BorrowMutError<'a>
969    where
970        T: 'a,
971    = BorrowMutError;
972
973    fn try_nonblocking_guarded_borrow_mut(
974        &self,
975    ) -> Result<Self::GuardMut<'_>, Self::BorrowMutError<'_>> {
976        self.as_inner().try_borrow_mut()
977    }
978}
979
980impl<T: ?Sized> NonBlockingGuardedMutBorrowMut<T> for ArcCell<T> {
981    type MutGuardMut<'a>
982    where
983        T: 'a,
984    = AtomicRefMut<'a, T>;
985    type MutBorrowMutError<'a>
986    where
987        T: 'a,
988    = BorrowMutError;
989
990    fn try_nonblocking_guarded_mut_borrow_mut(
991        &mut self,
992    ) -> Result<Self::MutGuardMut<'_>, Self::MutBorrowMutError<'_>> {
993        self.as_inner().try_borrow_mut()
994    }
995}
996
997impl<T: ?Sized, C: ?Sized> NonBlockingGuardedBorrow<T> for ArcRef<T, C> {
998    type Guard<'a>
999    where
1000        T: 'a,
1001        Self: 'a,
1002    = &'a T;
1003    type BorrowError<'a>
1004    where
1005        T: 'a,
1006        Self: 'a,
1007    = Infallible;
1008
1009    fn try_nonblocking_guarded_borrow(&self) -> Result<Self::Guard<'_>, Self::BorrowError<'_>> {
1010        Ok(self)
1011    }
1012}
1013
1014impl<T: ?Sized, C: ?Sized> NonBlockingGuardedMutBorrowMut<T> for ArcRef<T, C> {
1015    type MutGuardMut<'a>
1016    where
1017        T: 'a,
1018        Self: 'a,
1019    = &'a mut T;
1020    type MutBorrowMutError<'a>
1021    where
1022        T: 'a,
1023        Self: 'a,
1024    = &'static str;
1025
1026    fn try_nonblocking_guarded_mut_borrow_mut(
1027        &mut self,
1028    ) -> Result<Self::MutGuardMut<'_>, Self::MutBorrowMutError<'_>> {
1029        Err("cannot mutably borrow an `ArcRef`")
1030    }
1031}
1032
1033impl<T: ?Sized, C: ?Sized> NonBlockingGuardedBorrow<T> for ArcRefMut<T, C> {
1034    type Guard<'a>
1035    where
1036        T: 'a,
1037        Self: 'a,
1038    = &'a T;
1039    type BorrowError<'a>
1040    where
1041        T: 'a,
1042        Self: 'a,
1043    = Infallible;
1044
1045    fn try_nonblocking_guarded_borrow(&self) -> Result<Self::Guard<'_>, Self::BorrowError<'_>> {
1046        Ok(self)
1047    }
1048}
1049
1050impl<T: ?Sized, C: ?Sized> NonBlockingGuardedMutBorrowMut<T> for ArcRefMut<T, C> {
1051    type MutGuardMut<'a>
1052    where
1053        T: 'a,
1054        Self: 'a,
1055    = &'a mut T;
1056    type MutBorrowMutError<'a>
1057    where
1058        T: 'a,
1059        Self: 'a,
1060    = Infallible;
1061
1062    fn try_nonblocking_guarded_mut_borrow_mut(
1063        &mut self,
1064    ) -> Result<Self::MutGuardMut<'_>, Self::MutBorrowMutError<'_>> {
1065        Ok(self)
1066    }
1067}