use std::sync::{Arc, RwLock};
#[derive(Clone)]
pub struct ArcRW<T> {
inner: Arc<RwLock<T>>,
}
impl<T> ArcRW<T> {
pub fn new(value: T) -> ArcRW<T> {
ArcRW {
inner: Arc::new(RwLock::new(value)),
}
}
pub fn clone(&self) -> ArcRW<T> {
ArcRW {
inner: self.inner.clone(),
}
}
pub fn try_read(&self) -> Option<std::sync::RwLockReadGuard<T>> {
self.inner.try_read().ok()
}
pub fn try_write(&self) -> Option<std::sync::RwLockWriteGuard<T>> {
self.inner.try_write().ok()
}
pub fn read(&self) -> std::sync::RwLockReadGuard<T> {
self.try_read().expect("Failed to acquire read lock")
}
pub fn write(&self) -> std::sync::RwLockWriteGuard<T> {
self.try_write().expect("Failed to acquire write lock")
}
pub fn wait_read(&self) -> std::sync::RwLockReadGuard<T> {
#[cfg(any(debug_assertions, feature = "enable-release-validation"))]
let now = std::time::Instant::now();
loop {
if let Ok(guard) = self.inner.try_read() {
return guard;
}
#[cfg(any(debug_assertions, feature = "enable-release-validation"))]
if now.elapsed().as_secs() > 5 {
panic!("wait_read: waited more than 5 seconds to acquire read lock");
}
}
}
pub fn wait_write(&self) -> std::sync::RwLockWriteGuard<T> {
#[cfg(any(debug_assertions, feature = "enable-release-validation"))]
let now = std::time::Instant::now();
loop {
if let Ok(guard) = self.inner.try_write() {
return guard;
}
#[cfg(any(debug_assertions, feature = "enable-release-validation"))]
if now.elapsed().as_secs() > 5 {
panic!("wait_write: waited more than 5 seconds to acquire write lock");
}
}
}
pub fn into_inner(self) -> Result<T, Self> {
let inner = Arc::try_unwrap(self.inner);
match inner {
Ok(lock) => match lock.into_inner() {
Ok(value) => Ok(value),
Err(poison_err) => Err(Self {
inner: Arc::new(RwLock::new(poison_err.into_inner())),
}),
},
Err(val) => Err(Self { inner: val }),
}
}
}