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
10pub trait Guard<K>: Debug
12where
13 K: Eq + PartialEq + Hash + Clone + Debug,
14{
15 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 #[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}