1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Type definitions for putting shared ownership and synchronized mutation behind the `threading` feature toggle.
//!
//! That way, single-threaded applications will not have to use thread-safe primitives, and simply do not specify the 'threading' feature.

#[cfg(feature = "parallel")]
mod _impl {
    use std::sync::Arc;

    /// A reference counted pointer type for shared ownership.
    pub type OwnShared<T> = Arc<T>;
    /// A synchronization primitive which can start read-only and transition to support mutation.
    pub type MutableOnDemand<T> = parking_lot::RwLock<T>;
    /// A synchronization primitive which provides read-write access right away.
    pub type Mutable<T> = parking_lot::Mutex<T>;
    /// A guarded reference suitable for safekeeping in a struct.
    pub type RefGuard<'a, T> = parking_lot::RwLockReadGuard<'a, T>;
    /// A mapped reference created from a RefGuard
    pub type MappedRefGuard<'a, U> = parking_lot::MappedRwLockReadGuard<'a, U>;

    /// Get an upgradable shared reference through a [`MutableOnDemand`] for read-only access.
    ///
    /// This access can be upgraded using [`upgrade_ref_to_mut()`].
    pub fn get_ref_upgradeable<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockUpgradableReadGuard<'_, T> {
        v.upgradable_read()
    }

    /// Get a shared reference through a [`MutableOnDemand`] for read-only access.
    pub fn get_ref<T>(v: &MutableOnDemand<T>) -> RefGuard<'_, T> {
        v.read()
    }

    /// Get a mutable reference through a [`MutableOnDemand`] for read-write access.
    pub fn get_mut<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockWriteGuard<'_, T> {
        v.write()
    }

    /// Get a mutable reference through a [`Mutable`] for read-write access.
    pub fn lock<T>(v: &Mutable<T>) -> parking_lot::MutexGuard<'_, T> {
        v.lock()
    }

    /// Upgrade a handle previously obtained with [`get_ref_upgradeable()`] to support mutation.
    pub fn upgrade_ref_to_mut<'a, T>(
        v: parking_lot::RwLockUpgradableReadGuard<'a, T>,
        _orig: &'a MutableOnDemand<T>,
    ) -> parking_lot::RwLockWriteGuard<'a, T> {
        parking_lot::RwLockUpgradableReadGuard::upgrade(v)
    }

    /// Downgrade a handle previously obtained with [`upgrade_ref_to_mut()`] to drop mutation support.
    pub fn downgrade_mut_to_ref<'a, T>(
        v: parking_lot::RwLockWriteGuard<'a, T>,
        _orig: &'a MutableOnDemand<T>,
    ) -> RefGuard<'a, T> {
        parking_lot::RwLockWriteGuard::downgrade(v)
    }

    /// Map a read guard into a sub-type it contains.
    pub fn map_ref<T, U: ?Sized>(v: RefGuard<'_, T>, f: impl FnOnce(&T) -> &U) -> MappedRefGuard<'_, U> {
        parking_lot::RwLockReadGuard::map(v, f)
    }

    /// Map an upgradable read guard into a sub-type it contains.
    pub fn map_upgradable_ref<T, U: ?Sized>(
        v: parking_lot::RwLockUpgradableReadGuard<'_, T>,
        f: impl FnOnce(&T) -> &U,
    ) -> MappedRefGuard<'_, U> {
        let v = parking_lot::RwLockUpgradableReadGuard::downgrade(v);
        parking_lot::RwLockReadGuard::map(v, f)
    }
}

#[cfg(not(feature = "parallel"))]
mod _impl {
    use std::{
        cell::{Ref, RefCell, RefMut},
        rc::Rc,
    };

    /// A reference counted pointer type for shared ownership.
    pub type OwnShared<T> = Rc<T>;
    /// A synchronization primitive which can start read-only and transition to support mutation.
    pub type MutableOnDemand<T> = RefCell<T>;
    /// A synchronization primitive which provides read-write access right away.
    pub type Mutable<T> = RefCell<T>;
    /// A guarded reference suitable for safekeeping in a struct.
    pub type RefGuard<'a, T> = Ref<'a, T>;
    /// A mapped reference created from a RefGuard
    pub type MappedRefGuard<'a, U> = Ref<'a, U>;

    /// Get an upgradable shared reference through a [`MutableOnDemand`] for read-only access.
    ///
    /// This access can be upgraded using [`upgrade_ref_to_mut()`].
    pub fn get_ref_upgradeable<T>(v: &RefCell<T>) -> Ref<'_, T> {
        v.borrow()
    }

    /// Get a shared reference through a [`MutableOnDemand`] for read-only access.
    pub fn get_mut<T>(v: &RefCell<T>) -> RefMut<'_, T> {
        v.borrow_mut()
    }

    /// Get a mutable reference through a [`Mutable`] for read-write access.
    pub fn lock<T>(v: &Mutable<T>) -> RefMut<'_, T> {
        v.borrow_mut()
    }

    /// Get a mutable reference through a [`MutableOnDemand`] for read-write access.
    pub fn get_ref<T>(v: &RefCell<T>) -> RefGuard<'_, T> {
        v.borrow()
    }

    /// Upgrade a handle previously obtained with [`get_ref_upgradeable()`] to support mutation.
    pub fn upgrade_ref_to_mut<'a, T>(v: Ref<'a, T>, orig: &'a RefCell<T>) -> RefMut<'a, T> {
        drop(v);
        orig.borrow_mut()
    }

    /// Downgrade a handle previously obtained with [`upgrade_ref_to_mut()`] to drop mutation support.
    pub fn downgrade_mut_to_ref<'a, T>(v: RefMut<'a, T>, orig: &'a RefCell<T>) -> RefGuard<'a, T> {
        drop(v);
        orig.borrow()
    }

    /// Map a read guard into a sub-type it contains.
    pub fn map_ref<T, U: ?Sized>(v: RefGuard<'_, T>, f: impl FnOnce(&T) -> &U) -> MappedRefGuard<'_, U> {
        Ref::map(v, f)
    }

    /// Map an upgradable read guard into a sub-type it contains.
    pub fn map_upgradable_ref<T, U: ?Sized>(v: Ref<'_, T>, f: impl FnOnce(&T) -> &U) -> MappedRefGuard<'_, U> {
        Ref::map(v, f)
    }
}

pub use _impl::*;