Disallow taking two instances of the same mutex at the same time
[rust-lightning] / lightning / src / sync / mod.rs
1 #[allow(dead_code)] // Depending on the compilation flags some variants are never used
2 #[derive(Debug, PartialEq, Eq)]
3 pub(crate) enum LockHeldState {
4         HeldByThread,
5         NotHeldByThread,
6         #[cfg(any(feature = "_bench_unstable", not(test)))]
7         Unsupported,
8 }
9
10 pub(crate) trait LockTestExt<'a> {
11         fn held_by_thread(&self) -> LockHeldState;
12         type ExclLock;
13         /// If two instances of the same mutex are being taken at the same time, it's very easy to have
14         /// a lockorder inversion and risk deadlock. Thus, we default to disabling such locks.
15         ///
16         /// However, sometimes they cannot be avoided. In such cases, this method exists to take a
17         /// mutex while avoiding a test failure. It is deliberately verbose and includes the term
18         /// "unsafe" to indicate that special care needs to be taken to ensure no deadlocks are
19         /// possible.
20         fn unsafe_well_ordered_double_lock_self(&'a self) -> Self::ExclLock;
21 }
22
23 #[cfg(all(feature = "std", not(feature = "_bench_unstable"), test))]
24 mod debug_sync;
25 #[cfg(all(feature = "std", not(feature = "_bench_unstable"), test))]
26 pub use debug_sync::*;
27 #[cfg(all(feature = "std", not(feature = "_bench_unstable"), test))]
28 // Note that to make debug_sync's regex work this must not contain `debug_string` in the module name
29 mod test_lockorder_checks;
30
31 #[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
32 pub(crate) mod fairrwlock;
33 #[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
34 pub use {std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}, fairrwlock::FairRwLock};
35
36 #[cfg(all(feature = "std", any(feature = "_bench_unstable", not(test))))]
37 mod ext_impl {
38         use super::*;
39         impl<'a, T: 'a> LockTestExt<'a> for Mutex<T> {
40                 #[inline]
41                 fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported }
42                 type ExclLock = MutexGuard<'a, T>;
43                 #[inline]
44                 fn unsafe_well_ordered_double_lock_self(&'a self) -> MutexGuard<T> { self.lock().unwrap() }
45         }
46         impl<'a, T: 'a> LockTestExt<'a> for RwLock<T> {
47                 #[inline]
48                 fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported }
49                 type ExclLock = RwLockWriteGuard<'a, T>;
50                 #[inline]
51                 fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard<T> { self.write().unwrap() }
52         }
53 }
54
55 #[cfg(not(feature = "std"))]
56 mod nostd_sync;
57 #[cfg(not(feature = "std"))]
58 pub use nostd_sync::*;