parity_db/
parking_lot.rs

1#[cfg(feature = "loom")]
2pub use self::with_loom::*;
3
4#[cfg(not(feature = "loom"))]
5pub use parking_lot::*;
6
7#[cfg(feature = "loom")]
8mod with_loom {
9	use std::{
10		fmt,
11		ops::{Deref, DerefMut},
12	};
13
14	#[derive(Debug, Default)]
15	pub struct Mutex<T>(loom::sync::Mutex<T>);
16
17	impl<T> Mutex<T> {
18		pub fn new(val: T) -> Self {
19			Self(loom::sync::Mutex::new(val))
20		}
21
22		pub fn lock(&self) -> MutexGuard<T> {
23			MutexGuard(Some(self.0.lock().unwrap()))
24		}
25	}
26
27	#[derive(Debug)]
28	pub struct MutexGuard<'a, T>(Option<loom::sync::MutexGuard<'a, T>>);
29
30	impl<'a, T> Deref for MutexGuard<'a, T> {
31		type Target = T;
32
33		fn deref(&self) -> &T {
34			self.0.as_ref().unwrap().deref()
35		}
36	}
37
38	impl<'a, T> DerefMut for MutexGuard<'a, T> {
39		fn deref_mut(&mut self) -> &mut T {
40			self.0.as_mut().unwrap().deref_mut()
41		}
42	}
43
44	impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
45		fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46			self.0.as_ref().unwrap().fmt(f)
47		}
48	}
49
50	#[derive(Debug, Default)]
51	pub struct Condvar(loom::sync::Condvar);
52
53	impl Condvar {
54		pub fn new() -> Self {
55			Self(loom::sync::Condvar::new())
56		}
57
58		pub fn notify_one(&self) {
59			self.0.notify_one();
60		}
61
62		pub fn notify_all(&self) {
63			self.0.notify_all()
64		}
65
66		pub fn wait<T>(&self, mutex_guard: &mut MutexGuard<T>) {
67			mutex_guard.0 = Some(self.0.wait(mutex_guard.0.take().unwrap()).unwrap())
68		}
69	}
70
71	#[derive(Debug, Default)]
72	pub struct RwLock<T>(loom::sync::RwLock<T>);
73
74	impl<T> RwLock<T> {
75		pub fn new(val: T) -> Self {
76			Self(loom::sync::RwLock::new(val))
77		}
78
79		pub fn read(&self) -> RwLockReadGuard<T> {
80			RwLockReadGuard(self.0.read().unwrap())
81		}
82
83		pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<T> {
84			RwLockUpgradableReadGuard(self.0.write().unwrap())
85		}
86
87		pub fn write(&self) -> RwLockWriteGuard<T> {
88			RwLockWriteGuard(self.0.write().unwrap())
89		}
90	}
91
92	#[derive(Debug)]
93	pub struct RwLockReadGuard<'a, T>(loom::sync::RwLockReadGuard<'a, T>);
94
95	impl<'a, T> Deref for RwLockReadGuard<'a, T> {
96		type Target = T;
97
98		fn deref(&self) -> &T {
99			self.0.deref()
100		}
101	}
102
103	/// We use here a write gard and not a read gard to avoid an other thread "stealing" the write
104	/// lock during upgrade.
105	///
106	/// Indeed, if we had used a read gard here, to get a write gard we would have to release the
107	/// read gard first, allowing an other thread to grab a write gard at this time and change the
108	/// protected value state.
109	#[derive(Debug)]
110	pub struct RwLockUpgradableReadGuard<'a, T>(loom::sync::RwLockWriteGuard<'a, T>);
111
112	impl<'a, T> RwLockUpgradableReadGuard<'a, T> {
113		pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, T> {
114			RwLockWriteGuard(s.0)
115		}
116	}
117
118	impl<'a, T> Deref for RwLockUpgradableReadGuard<'a, T> {
119		type Target = T;
120
121		fn deref(&self) -> &T {
122			self.0.deref()
123		}
124	}
125
126	#[derive(Debug)]
127	pub struct RwLockWriteGuard<'a, T>(loom::sync::RwLockWriteGuard<'a, T>);
128
129	impl<'a, T> RwLockWriteGuard<'a, T> {
130		pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, T> {
131			RwLockUpgradableReadGuard(s.0)
132		}
133	}
134
135	impl<'a, T> Deref for RwLockWriteGuard<'a, T> {
136		type Target = T;
137
138		fn deref(&self) -> &T {
139			self.0.deref()
140		}
141	}
142
143	impl<'a, T> DerefMut for RwLockWriteGuard<'a, T> {
144		fn deref_mut(&mut self) -> &mut T {
145			self.0.deref_mut()
146		}
147	}
148}