parity-db 0.5.4

Key-value database for the blockchain
Documentation
#[cfg(feature = "loom")]
pub use self::with_loom::*;

#[cfg(not(feature = "loom"))]
pub use parking_lot::*;

#[cfg(feature = "loom")]
mod with_loom {
	use std::{
		fmt,
		ops::{Deref, DerefMut},
	};

	#[derive(Debug, Default)]
	pub struct Mutex<T>(loom::sync::Mutex<T>);

	impl<T> Mutex<T> {
		pub fn new(val: T) -> Self {
			Self(loom::sync::Mutex::new(val))
		}

		pub fn lock(&self) -> MutexGuard<T> {
			MutexGuard(Some(self.0.lock().unwrap()))
		}
	}

	#[derive(Debug)]
	pub struct MutexGuard<'a, T>(Option<loom::sync::MutexGuard<'a, T>>);

	impl<'a, T> Deref for MutexGuard<'a, T> {
		type Target = T;

		fn deref(&self) -> &T {
			self.0.as_ref().unwrap().deref()
		}
	}

	impl<'a, T> DerefMut for MutexGuard<'a, T> {
		fn deref_mut(&mut self) -> &mut T {
			self.0.as_mut().unwrap().deref_mut()
		}
	}

	impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
		fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
			self.0.as_ref().unwrap().fmt(f)
		}
	}

	#[derive(Debug, Default)]
	pub struct Condvar(loom::sync::Condvar);

	impl Condvar {
		pub fn new() -> Self {
			Self(loom::sync::Condvar::new())
		}

		pub fn notify_one(&self) {
			self.0.notify_one();
		}

		pub fn notify_all(&self) {
			self.0.notify_all()
		}

		pub fn wait<T>(&self, mutex_guard: &mut MutexGuard<T>) {
			mutex_guard.0 = Some(self.0.wait(mutex_guard.0.take().unwrap()).unwrap())
		}
	}

	#[derive(Debug, Default)]
	pub struct RwLock<T>(loom::sync::RwLock<T>);

	impl<T> RwLock<T> {
		pub fn new(val: T) -> Self {
			Self(loom::sync::RwLock::new(val))
		}

		pub fn read(&self) -> RwLockReadGuard<T> {
			RwLockReadGuard(self.0.read().unwrap())
		}

		pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<T> {
			RwLockUpgradableReadGuard(self.0.write().unwrap())
		}

		pub fn write(&self) -> RwLockWriteGuard<T> {
			RwLockWriteGuard(self.0.write().unwrap())
		}

		pub fn is_locked(&self) -> bool {
			!self.0.try_write().is_ok()
		}
	}

	#[derive(Debug)]
	pub struct RwLockReadGuard<'a, T>(loom::sync::RwLockReadGuard<'a, T>);

	impl<'a, T> Deref for RwLockReadGuard<'a, T> {
		type Target = T;

		fn deref(&self) -> &T {
			self.0.deref()
		}
	}

	/// We use here a write gard and not a read gard to avoid an other thread "stealing" the write
	/// lock during upgrade.
	///
	/// Indeed, if we had used a read gard here, to get a write gard we would have to release the
	/// read gard first, allowing an other thread to grab a write gard at this time and change the
	/// protected value state.
	#[derive(Debug)]
	pub struct RwLockUpgradableReadGuard<'a, T>(loom::sync::RwLockWriteGuard<'a, T>);

	impl<'a, T> RwLockUpgradableReadGuard<'a, T> {
		pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, T> {
			RwLockWriteGuard(s.0)
		}
	}

	impl<'a, T> Deref for RwLockUpgradableReadGuard<'a, T> {
		type Target = T;

		fn deref(&self) -> &T {
			self.0.deref()
		}
	}

	#[derive(Debug)]
	pub struct RwLockWriteGuard<'a, T>(loom::sync::RwLockWriteGuard<'a, T>);

	impl<'a, T> RwLockWriteGuard<'a, T> {
		pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, T> {
			RwLockUpgradableReadGuard(s.0)
		}
	}

	impl<'a, T> Deref for RwLockWriteGuard<'a, T> {
		type Target = T;

		fn deref(&self) -> &T {
			self.0.deref()
		}
	}

	impl<'a, T> DerefMut for RwLockWriteGuard<'a, T> {
		fn deref_mut(&mut self) -> &mut T {
			self.0.deref_mut()
		}
	}
}