lockpool/
guard.rs

1use owning_ref_lockable::OwningHandle;
2use std::fmt::{self, Debug};
3use std::hash::Hash;
4use std::ops::Deref;
5use std::sync::Arc;
6
7use super::mutex::MutexImpl;
8use crate::pool::LockPoolImpl;
9
10/// A RAII implementation of a scoped lock for locks from a [LockPool]. When this instance is dropped (falls out of scope), the lock will be unlocked.
11pub trait Guard<K>: Debug
12where
13    K: Eq + PartialEq + Hash + Clone + Debug,
14{
15    /// Returns the key locked by this guard
16    fn key(&self) -> &K;
17}
18
19#[must_use = "if unused the Mutex will immediately unlock"]
20pub struct GuardImpl<'a, K, M, P>
21where
22    K: Eq + PartialEq + Hash + Clone + Debug,
23    M: MutexImpl + 'a,
24    P: Deref<Target = LockPoolImpl<K, M>>,
25{
26    pool: P,
27    key: K,
28    guard: Option<OwningHandle<Arc<M>, M::Guard<'a>>>,
29    poisoned: bool,
30}
31
32impl<'a, K, M, P> GuardImpl<'a, K, M, P>
33where
34    K: Eq + PartialEq + Hash + Clone + Debug,
35    M: MutexImpl + 'a,
36    P: Deref<Target = LockPoolImpl<K, M>>,
37{
38    pub(super) fn new(
39        pool: P,
40        key: K,
41        guard: OwningHandle<Arc<M>, M::Guard<'a>>,
42        poisoned: bool,
43    ) -> Self {
44        Self {
45            pool,
46            key,
47            guard: Some(guard),
48            poisoned,
49        }
50    }
51}
52
53impl<'a, K, M, P> Guard<K> for GuardImpl<'a, K, M, P>
54where
55    K: Eq + PartialEq + Hash + Clone + Debug,
56    M: MutexImpl + 'a,
57    P: Deref<Target = LockPoolImpl<K, M>>,
58{
59    /// TODO Test
60    #[inline]
61    fn key(&self) -> &K {
62        &self.key
63    }
64}
65
66impl<'a, K, M, P> Drop for GuardImpl<'a, K, M, P>
67where
68    K: Eq + PartialEq + Hash + Clone + Debug,
69    M: MutexImpl + 'a,
70    P: Deref<Target = LockPoolImpl<K, M>>,
71{
72    fn drop(&mut self) {
73        let guard = self
74            .guard
75            .take()
76            .expect("The self.guard field must always be set unless this was already destructed");
77        self.pool._unlock(&self.key, guard, self.poisoned);
78    }
79}
80
81impl<'a, K, M, P> Debug for GuardImpl<'a, K, M, P>
82where
83    K: Eq + PartialEq + Hash + Clone + Debug,
84    M: MutexImpl + 'a,
85    P: Deref<Target = LockPoolImpl<K, M>>,
86{
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "GuardImpl({:?})", self.key)
89    }
90}