use super::*;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_void;
#[derive(Debug)]
pub enum LockType {
Mutex,
RwLock,
None,
}
#[doc(hidden)]
pub struct LockNone {}
impl SharedMemLockImpl for LockNone {
fn size_of() -> usize {0}
fn rlock(&self, _lock_data: *mut c_void) -> Result<()> {Ok(())}
fn wlock(&self, _lock_data: *mut c_void) -> Result<()> {Ok(())}
fn runlock(&self, _lock_data: *mut c_void) -> () {}
fn wunlock(&self, _lock_data: *mut c_void) -> () {}
}
#[doc(hidden)] pub trait SharedMemLockImpl {
fn size_of() -> usize where Self: Sized;
fn rlock(&self, lock_ptr: *mut c_void) -> Result<()>;
fn wlock(&self, lock_ptr: *mut c_void) -> Result<()>;
fn runlock(&self, lock_ptr: *mut c_void) -> ();
fn wunlock(&self, lock_ptr: *mut c_void) -> ();
}
pub trait SharedMemLockable {
fn rlock<D: SharedMemCast>(&self) -> Result<ReadLockGuard<D>>;
fn rlock_as_slice<D: SharedMemCast>(&self) -> Result<ReadLockGuardSlice<D>>;
fn wlock<D: SharedMemCast>(&mut self) -> Result<WriteLockGuard<D>>;
fn wlock_as_slice<D: SharedMemCast>(&mut self) -> Result<WriteLockGuardSlice<D>>;
}
impl<'a>SharedMemLockable for SharedMem<'a> {
fn rlock<D: SharedMemCast>(&self) -> Result<ReadLockGuard<D>> {
if let Some(ref meta) = self.meta {
let type_size = std::mem::size_of::<D>();
if type_size > self.size {
return Err(From::from(
format!("Tried to map SharedMem to a too big type {}/{}", type_size, self.size)
));
}
Ok(unsafe {
ReadLockGuard::lock(
&(*(meta.data as *const D)),
meta.lock_impl,
&mut (*meta.lock_data),
)
})
} else {
return Err(From::from("No file mapped to get lock on"));
}
}
fn rlock_as_slice<D: SharedMemCast>(&self) -> Result<ReadLockGuardSlice<D>> {
if let Some(ref meta) = self.meta {
let item_size = std::mem::size_of::<D>();
if item_size > self.size {
return Err(From::from(
format!("Tried to map SharedMem to a too big type {}/{}", item_size, self.size)
));
}
let num_items: usize = self.size / item_size;
Ok(unsafe {
ReadLockGuardSlice::lock(
slice::from_raw_parts((meta.data as usize + 0) as *const D, num_items),
meta.lock_impl,
&mut (*meta.lock_data),
)
})
} else {
return Err(From::from("No file mapped to get lock on"));
}
}
fn wlock<D: SharedMemCast>(&mut self) -> Result<WriteLockGuard<D>> {
if let Some(ref mut meta) = self.meta {
let type_size = std::mem::size_of::<D>();
if type_size > self.size {
return Err(From::from(
format!("Tried to map SharedMem to a too big type {}/{}", type_size, self.size)
));
}
Ok(unsafe {
WriteLockGuard::lock(
&mut (*(meta.data as *mut D)),
meta.lock_impl,
&mut (*meta.lock_data),
)
})
} else {
return Err(From::from("No file mapped to get lock on"));
}
}
fn wlock_as_slice<D: SharedMemCast>(&mut self) -> Result<WriteLockGuardSlice<D>> {
if let Some(ref mut meta) = self.meta {
let item_size = std::mem::size_of::<D>();
if item_size > self.size {
return Err(From::from(
format!("Tried to map SharedMem to a too big type {}/{}", item_size, self.size)
));
}
let num_items: usize = self.size / item_size;
Ok(unsafe {
WriteLockGuardSlice::lock(
slice::from_raw_parts_mut((meta.data as usize + 0) as *mut D, num_items),
meta.lock_impl,
&mut (*meta.lock_data),
)
})
} else {
return Err(From::from("No file mapped to get lock on"));
}
}
}
pub struct ReadLockGuard<'a, T: 'a> {
data: &'a T,
lock_fn: &'a SharedMemLockImpl,
lock_data: &'a mut c_void,
}
impl<'a, T:'a> ReadLockGuard<'a, T> {
#[doc(hidden)]
pub fn lock(data_in: &'a T, lock_fn_in: &'a SharedMemLockImpl, lock_data_in: &'a mut c_void) -> ReadLockGuard<'a, T> {
lock_fn_in.rlock(lock_data_in).unwrap();
ReadLockGuard {
data: data_in,
lock_fn: lock_fn_in,
lock_data: lock_data_in,
}
}
}
impl<'a, T: 'a> Drop for ReadLockGuard<'a, T> {
fn drop(&mut self) -> () {
self.lock_fn.runlock(self.lock_data);
}
}
impl<'a, T> Deref for ReadLockGuard<'a, T> {
type Target = &'a T;
fn deref(&self) -> &Self::Target { &self.data }
}
pub struct ReadLockGuardSlice<'a, T: 'a> {
data: &'a [T],
lock_fn: &'a SharedMemLockImpl,
lock_data: &'a mut c_void,
}
impl<'a, T:'a> ReadLockGuardSlice<'a, T> {
#[doc(hidden)]
pub fn lock(data_in: &'a [T], lock_fn_in: &'a SharedMemLockImpl, lock_data_in: &'a mut c_void) -> ReadLockGuardSlice<'a, T> {
lock_fn_in.rlock(lock_data_in).unwrap();
ReadLockGuardSlice {
data: data_in,
lock_fn: lock_fn_in,
lock_data: lock_data_in,
}
}
}
impl<'a, T: 'a> Drop for ReadLockGuardSlice<'a, T> {
fn drop(&mut self) -> () {
self.lock_fn.runlock(self.lock_data);
}
}
impl<'a, T> Deref for ReadLockGuardSlice<'a, T> {
type Target = &'a [T];
fn deref(&self) -> &Self::Target { &self.data }
}
pub struct WriteLockGuard<'a, T: 'a> {
data: &'a mut T,
lock_fn: &'a SharedMemLockImpl,
lock_data: &'a mut c_void,
}
impl<'a, T:'a> WriteLockGuard<'a, T> {
#[doc(hidden)]
pub fn lock(data_in: &'a mut T, lock_fn_in: &'a SharedMemLockImpl, lock_data_in: &'a mut c_void) -> WriteLockGuard<'a, T> {
lock_fn_in.wlock(lock_data_in).unwrap();
WriteLockGuard {
data: data_in,
lock_fn: lock_fn_in,
lock_data: lock_data_in,
}
}
}
impl<'a, T: 'a> Drop for WriteLockGuard<'a, T> {
fn drop(&mut self) -> () {
self.lock_fn.wunlock(self.lock_data);
}
}
impl<'a, T> Deref for WriteLockGuard<'a, T> {
type Target = &'a mut T;
fn deref(&self) -> &Self::Target { &self.data }
}
impl<'a, T> DerefMut for WriteLockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut &'a mut T {
&mut self.data
}
}
pub struct WriteLockGuardSlice<'a, T: 'a> {
data: &'a mut [T],
lock_fn: &'a SharedMemLockImpl,
lock_data: &'a mut c_void,
}
impl<'a, T:'a> WriteLockGuardSlice<'a, T> {
#[doc(hidden)]
pub fn lock(data_in: &'a mut [T], lock_fn_in: &'a SharedMemLockImpl, lock_data_in: &'a mut c_void) -> WriteLockGuardSlice<'a, T> {
lock_fn_in.wlock(lock_data_in).unwrap();
WriteLockGuardSlice {
data: data_in,
lock_fn: lock_fn_in,
lock_data: lock_data_in,
}
}
}
impl<'a, T: 'a> Drop for WriteLockGuardSlice<'a, T> {
fn drop(&mut self) -> () {
self.lock_fn.wunlock(self.lock_data);
}
}
impl<'a, T> Deref for WriteLockGuardSlice<'a, T> {
type Target = &'a mut [T];
fn deref(&self) -> &Self::Target { &self.data }
}
impl<'a, T> DerefMut for WriteLockGuardSlice<'a, T> {
fn deref_mut(&mut self) -> &mut &'a mut [T] {
&mut self.data
}
}