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
use crate::mutex::{CustomMutex, CustomMutexGuard, RawMutex, TryMutex, TryMutexSized};
use core::ops::DerefMut;
use core::time::Duration;

/// A raw mutex that can be timed out and holds no data.
pub unsafe trait RawTimeoutMutex: RawMutex {
    /// Locks the mutex on a timeout. Returns true if locked.
    fn lock_timeout(&self, timeout: Duration) -> bool;
}
/// A mutex that can timeout for locking
///
/// ## Implementation
/// It is recommended to implement [`TimeoutMutexSized`] if the implement-ee can
/// be sized.
pub trait TimeoutMutex<'a>: TryMutex<'a> {
    /// Locks the mutex blocking for timeout or until locked
    fn lock_timeout(&'a self, timeout: Duration) -> Option<Self::Guard>;
}
/// The functions for [`TimeoutMutex`] that only work for sized types.
/// Separated to allow [`TimeoutMutex`] to be a trait object.
pub trait TimeoutMutexSized<'a>: Sized + TimeoutMutex<'a> + TryMutexSized<'a> {
    /// Attempts to lock the mutex before timeout has passed and runs func on
    /// the result
    ///
    /// ## Implementation
    /// Should be overwritten by implementors if can be more optimal than
    /// creating a guard
    fn lock_timeout_func<O>(
        &'a self,
        timeout: Duration,
        func: impl FnOnce(Option<&mut Self::Item>) -> O,
    ) -> O {
        match self.lock_timeout(timeout) {
            None => func(None),
            Some(mut guard) => func(Some(guard.deref_mut())),
        }
    }
}

impl<'a, T, M> TimeoutMutex<'a> for CustomMutex<T, M>
where
    T: 'a,
    M: RawTimeoutMutex + 'a,
{
    fn lock_timeout(&'a self, timeout: Duration) -> Option<Self::Guard> {
        match self.raw_mutex.lock_timeout(timeout) {
            true => Some(CustomMutexGuard { mutex: self }),
            false => None,
        }
    }
}
impl<'a, T, M> TimeoutMutexSized<'a> for CustomMutex<T, M>
where
    T: 'a,
    M: RawTimeoutMutex + 'a,
{
    fn lock_timeout_func<O>(
        &'a self,
        timeout: Duration,
        func: impl FnOnce(Option<&mut Self::Item>) -> O,
    ) -> O {
        match self.raw_mutex.lock_timeout(timeout) {
            true => unsafe {
                let out = func(Some(&mut *self.data.get()));
                self.raw_mutex.unlock();
                out
            },
            false => func(None),
        }
    }
}