use std::sync::{RwLock, RwLockReadGuard, LockResult, PoisonError};
pub struct Actor<T: ?Sized> {
pub lock: Option<RwLock<()>>,
pub data: T
}
unsafe impl<T> Sync for Actor<T> {}
unsafe impl<T> Send for Actor<T> {}
impl<T: ?Sized> Actor<T> {
pub unsafe fn uninitialized() -> Actor<T> where T: Sized {
Actor {
lock: None,
data: unsafe { std::mem::uninitialized() }
}
}
pub fn new(t: T) -> Actor<T> where T: Sized {
Actor {
lock: Some(RwLock::new(())),
data: t
}
}
}
pub struct ActorReadGuard<'a, T: 'a + ?Sized> {
guard: RwLockReadGuard<'a, ()>,
data: &'a T
}
impl<T: ?Sized> Actor<T> {
pub unsafe fn initialize(&mut self, mut t: T) where T: Sized {
self.lock = Some(RwLock::new(()));
std::mem::swap(&mut self.data, &mut t);
std::mem::forget(t);
}
pub fn is_initialized(&self) -> bool {
self.lock.is_some()
}
pub fn read<'a>(&self) -> LockResult<ActorReadGuard<T>> {
match &self.lock {
Some(lock) => {
match lock.read() {
Ok(guard) => Ok(ActorReadGuard {
guard: guard,
data: &self.data
}),
Err(e) => Err(PoisonError::new(ActorReadGuard {
guard: e.into_inner(),
data: &self.data
}))
}
},
None => {
panic!("unallocated data")
}
}
}
}