use parking_lot::{
MappedRwLockReadGuard,
MappedRwLockWriteGuard, RwLock,
RwLockReadGuard,
RwLockWriteGuard,
};
use std::sync::Arc;
#[derive(Debug)]
pub struct ContextData<T: Send + Sync + 'static>(Arc<RwLock<T>>);
impl<T: Send + Sync + 'static> ContextData<T> {
pub fn new(data: T) -> Self {
ContextData(Arc::new(RwLock::new(data)))
}
pub fn read(&self) -> RwLockReadGuard<'_, T> {
self.0.read() }
pub fn write(&self) -> RwLockWriteGuard<'_, T> {
self.0.write()
}
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
self.0.try_read()
}
pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
self.0.try_write()
}
pub fn map_read<F, U: ?Sized>(&self, f: F) -> MappedRwLockReadGuard<'_, U>
where
F: FnOnce(&T) -> &U,
{
RwLockReadGuard::map(self.read(), f)
}
pub fn map_write<F, U: ?Sized>(&self, f: F) -> MappedRwLockWriteGuard<'_, U>
where
F: FnOnce(&mut T) -> &mut U,
{
RwLockWriteGuard::map(self.write(), f)
}
pub fn project<U, F>(&self, get: F) -> ContextData<U>
where
U: Send + Sync + 'static,
F: FnOnce(&T) -> U,
{
let projected = {
let guard = self.read();
get(&*guard)
};
ContextData::new(projected)
}
}
impl<T: Send + Sync + 'static> Clone for ContextData<T> {
fn clone(&self) -> Self {
ContextData(Arc::clone(&self.0))
}
}
impl<T: Send + Sync + 'static + Default> Default for ContextData<T> {
fn default() -> Self {
Self::new(Default::default())
}
}