2020-01-06 06:30:37 +00:00
|
|
|
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
2021-10-19 00:30:40 +00:00
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
2020-01-06 06:30:37 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
/// A simple wrapper around `parking_lot::RwLock` that only permits read/write access with a
|
|
|
|
/// time-out (i.e., no indefinitely-blocking operations).
|
2021-10-19 00:30:40 +00:00
|
|
|
///
|
|
|
|
/// Timeouts can be optionally be disabled at runtime for all instances of this type by calling
|
|
|
|
/// `TimeoutRwLock::disable_timeouts()`.
|
2020-01-06 06:30:37 +00:00
|
|
|
pub struct TimeoutRwLock<T>(RwLock<T>);
|
|
|
|
|
2021-10-19 00:30:40 +00:00
|
|
|
const TIMEOUT_LOCKS_ENABLED_DEFAULT: bool = true;
|
|
|
|
static TIMEOUT_LOCKS_ENABLED: AtomicBool = AtomicBool::new(TIMEOUT_LOCKS_ENABLED_DEFAULT);
|
|
|
|
|
|
|
|
impl TimeoutRwLock<()> {
|
|
|
|
pub fn disable_timeouts() {
|
|
|
|
// Use the strongest `SeqCst` ordering for the write, as it should only happen once.
|
|
|
|
TIMEOUT_LOCKS_ENABLED.store(false, Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-06 06:30:37 +00:00
|
|
|
impl<T> TimeoutRwLock<T> {
|
|
|
|
pub fn new(inner: T) -> Self {
|
|
|
|
Self(RwLock::new(inner))
|
|
|
|
}
|
|
|
|
|
2021-10-19 00:30:40 +00:00
|
|
|
fn timeouts_enabled() -> bool {
|
|
|
|
// Use relaxed ordering as it's OK for a few locks to run with timeouts "accidentally",
|
|
|
|
// and we want the atomic check to be as fast as possible.
|
|
|
|
TIMEOUT_LOCKS_ENABLED.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
2020-01-06 06:30:37 +00:00
|
|
|
pub fn try_read_for(&self, timeout: Duration) -> Option<RwLockReadGuard<T>> {
|
2021-10-19 00:30:40 +00:00
|
|
|
if Self::timeouts_enabled() {
|
|
|
|
self.0.try_read_for(timeout)
|
|
|
|
} else {
|
|
|
|
Some(self.0.read())
|
|
|
|
}
|
2020-01-06 06:30:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn try_write_for(&self, timeout: Duration) -> Option<RwLockWriteGuard<T>> {
|
2021-10-19 00:30:40 +00:00
|
|
|
if Self::timeouts_enabled() {
|
|
|
|
self.0.try_write_for(timeout)
|
|
|
|
} else {
|
|
|
|
Some(self.0.write())
|
|
|
|
}
|
2020-01-06 06:30:37 +00:00
|
|
|
}
|
|
|
|
}
|