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
//! Traits for RwLocks

mod impls;
pub use impls::*;

#[cfg(feature = "alloc")]
mod r#async;
#[cfg(feature = "alloc")]
pub use r#async::*;

#[cfg(feature = "alloc")]
mod async_timout;
#[cfg(feature = "alloc")]
pub use async_timout::*;

mod custom;
pub use custom::*;

mod timeout;
pub use timeout::*;

mod r#try;
pub use r#try::*;

mod upgrade_rw_lock;
pub use upgrade_rw_lock::*;

use core::ops::{Deref, DerefMut};

/// A raw rw lock that stores no data
pub unsafe trait RawRwLock: RawTryRwLock {
    /// Blocks until a reader is added to this lock
    fn add_reader(&self);
    /// Blocks until a writer is added to this lock
    fn add_writer(&self);
}
/// A generic blocking reader-writer lock trait
///
/// ## Implementation
/// It is recommended to implement [`RwLockSized`] if the implement-ee can be
/// sized.
pub trait RwLock<'a>: TryRwLock<'a> {
    /// Reads from the lock, blocking until able.
    fn read(&'a self) -> Self::ReadGuard;

    /// Writes to the lock, blocking until able.
    fn write(&'a self) -> Self::WriteGuard;
}
/// The functions for [`RwLock`] that only work for sized types.
/// Separated to allow [`RwLock`] to be a trait object.
pub trait RwLockSized<'a>: Sized + RwLock<'a> + TryRwLockSized<'a> {
    /// Blocks until reading from the lock and then runs `func` on the result
    ///
    /// ## Implementation
    /// Should be overwritten by implementors if can be more optimal than
    /// creating a guard
    fn read_func<O>(&'a self, func: impl FnOnce(&Self::Item) -> O) -> O {
        func(self.read().deref())
    }

    /// Blocks until writing to the lock and then runs `func` on the result
    ///
    /// ## Implementation
    /// Should be overwritten by implementors if can be more optimal than
    /// creating a guard
    fn write_func<O>(&'a self, func: impl FnOnce(&mut Self::Item) -> O) -> O {
        func(self.write().deref_mut())
    }
}

impl<'a, T, R> RwLock<'a> for CustomRwLock<T, R>
where
    T: 'a,
    R: RawRwLock + 'a,
{
    fn read(&'a self) -> Self::ReadGuard {
        self.raw_lock.add_reader();
        CustomReadGuard { lock: self }
    }

    fn write(&'a self) -> Self::WriteGuard {
        self.raw_lock.add_writer();
        CustomWriteGuard { lock: self }
    }
}
impl<'a, T, R> RwLockSized<'a> for CustomRwLock<T, R>
where
    T: 'a,
    R: RawRwLock + 'a,
{
    fn read_func<O>(&'a self, func: impl FnOnce(&Self::Item) -> O) -> O {
        self.raw_lock.add_reader();
        let out = func(unsafe { &*self.data.get() });
        unsafe { self.raw_lock.remove_reader() }
        out
    }

    fn write_func<O>(&'a self, func: impl FnOnce(&mut Self::Item) -> O) -> O {
        self.raw_lock.add_writer();
        let out = func(unsafe { &mut *self.data.get() });
        unsafe { self.raw_lock.remove_writer() }
        out
    }
}