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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::{
    cell::UnsafeCell,
    ops::{Deref, DerefMut},
    sync::atomic::{AtomicBool, Ordering},
};

///
/// A special RwLock which can be locked exclusively any number of consecutive times,
///  but once initially locked shared, can never be unlocked.
/// This allows unguarded reads to occur
pub struct FusedRwLock<T: ?Sized> {
    inner: parking_lot::RwLock<()>,
    locked: AtomicBool,
    object: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Send for FusedRwLock<T> {}
unsafe impl<T: ?Sized + Send + Sync> Sync for FusedRwLock<T> {}

impl<T: Default> Default for FusedRwLock<T> {
    fn default() -> Self {
        Self::new(Default::default())
    }
}

impl<T> FusedRwLock<T> {
    ///
    /// Constructs a new, initially unlocked, RwLock
    pub const fn new(x: T) -> Self {
        Self {
            inner: parking_lot::const_rwlock(()),
            locked: AtomicBool::new(false),
            object: UnsafeCell::new(x),
        }
    }

    ///
    /// Moves the inner value out of the FusedRwLock.
    /// This is sound because self is moved into the function, and thus no other accesses exist
    pub fn into_inner(self) -> T {
        self.object.into_inner()
    }
}

impl<T: ?Sized> FusedRwLock<T> {
    ///
    /// Mutably borrows the interior of the lock, if it has not been locked for reading access
    /// This is sound because taking self by &mut statically guarantees no other accesses exist.
    /// Returns None if the lock has been locked for reading
    pub fn try_get_mut(&mut self) -> Option<&mut T> {
        if *self.locked.get_mut() {
            Some(self.object.get_mut())
        } else {
            None
        }
    }

    ///
    /// Mutably borrows the interior of the lock, even if it has been locked for reading.
    /// This function is unsafe because, while not necessarily undefined behaviour, calling this function
    ///  after it was locked for reading can be used to violate the logical invariant of FusedRwLock.
    pub unsafe fn get_mut_unlocked(&mut self) -> &mut T {
        self.object.get_mut()
    }

    ///
    /// Check if the FusedRwLock has been locked for reading.
    /// This does not guarantee any synchronization, even if it returns true. Except where self is reborrowed from &mut,
    ///  it should only be used as a hint to avoid needless calls to self.try_read
    /// A return of true is guaranteed to remain true for the lifetime of the lock.
    /// A return of false may be invalidated at any time.
    pub fn is_locked(&self) -> bool {
        self.locked.load(Ordering::Relaxed)
    }

    ///
    /// Locks this FusedRwLock for reading.
    /// After this call, it becomes impossible to acquire the lock for writing,
    ///  and safe code cannot be used to modify the inner value (except inside an UnsafeCell)
    pub fn lock(&self) {
        let _guard = self.inner.read();
        self.locked
            .store(true, std::sync::atomic::Ordering::Release)
    }

    ///
    /// Returns a shared reference to the interior of the lock, if it has been locked for reading.
    pub fn try_read(&self) -> Option<&T> {
        if self.locked.load(Ordering::Acquire) {
            // Safety:
            // Because self.locked is set, the lock can never be borrowed exclusively again
            Some(unsafe { &*self.object.get() })
        } else {
            None
        }
    }

    ///
    /// Locks the RwLock for reading, and returns a shared reference to the interior of the lock
    pub fn read(&self) -> &T {
        if !self.is_locked() {
            self.lock();
        }
        self.try_read().unwrap()
    }

    ///
    /// Acquires an exclusive lock to the interior of the lock, if this lock has not already been locked for reading.
    /// Otherwise, returns None
    pub fn try_write(&self) -> Option<FusedRwLockGuard<T>> {
        // Optimization, since a true return from self.is_locked is guaranteed to continue forever
        if !self.is_locked() {
            let guard = self.inner.write();
            if !self.is_locked() {
                Some(FusedRwLockGuard {
                    _guard: guard,
                    // Safety:
                    // Because self.locked is not set, there are no readers. Other writers are excluded by the fact that the WriteGuard is held.
                    inner: unsafe { &mut *self.object.get() },
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

///
/// An RAII guard that holds exclusive mutable access to the inner object.
pub struct FusedRwLockGuard<'a, T: ?Sized> {
    inner: &'a mut T,
    _guard: parking_lot::RwLockWriteGuard<'a, ()>,
}

impl<'a, T: ?Sized> Deref for FusedRwLockGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        // SAFETY:
        // self.guard ensures that self.cell can be borrowed
        self.inner
    }
}

impl<'a, T: ?Sized> DerefMut for FusedRwLockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        // SAFETY:
        // self.guard ensures that self.cell can be borrowed
        self.inner
    }
}