mcrl2/aterm/
busy_forbidden.rsuse std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::Deref;
use std::ops::DerefMut;
use mcrl2_sys::atermpp::ffi;
pub struct BfTermPool<T: ?Sized> {
object: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for BfTermPool<T> {}
unsafe impl<T: Send> Sync for BfTermPool<T> {}
impl<T> BfTermPool<T> {
pub fn new(object: T) -> BfTermPool<T> {
BfTermPool {
object: UnsafeCell::new(object),
}
}
}
impl<'a, T: ?Sized> BfTermPool<T> {
pub fn read(&'a self) -> BfTermPoolRead<'a, T> {
ffi::lock_shared();
BfTermPoolRead {
mutex: self,
_marker: Default::default(),
}
}
pub fn write(&'a self) -> BfTermPoolWrite<'a, T> {
ffi::lock_exclusive();
BfTermPoolWrite {
mutex: self,
_marker: Default::default(),
}
}
pub unsafe fn get(&'a self) -> &'a T {
unsafe { &*self.object.get() }
}
pub unsafe fn write_exclusive(&'a self) -> BfTermPoolThreadWrite<'a, T> {
ffi::lock_shared();
BfTermPoolThreadWrite {
mutex: self,
locked: true,
_marker: Default::default(),
}
}
}
pub struct BfTermPoolRead<'a, T: ?Sized> {
mutex: &'a BfTermPool<T>,
_marker: PhantomData<&'a ()>,
}
impl<T: ?Sized> Deref for BfTermPoolRead<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.object.get() }
}
}
impl<T: ?Sized> Drop for BfTermPoolRead<'_, T> {
fn drop(&mut self) {
ffi::unlock_shared();
}
}
pub struct BfTermPoolWrite<'a, T: ?Sized> {
mutex: &'a BfTermPool<T>,
_marker: PhantomData<&'a ()>,
}
impl<T: ?Sized> Deref for BfTermPoolWrite<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.object.get() }
}
}
impl<T: ?Sized> DerefMut for BfTermPoolWrite<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mutex.object.get() }
}
}
impl<T: ?Sized> Drop for BfTermPoolWrite<'_, T> {
fn drop(&mut self) {
ffi::unlock_exclusive();
}
}
pub struct BfTermPoolThreadWrite<'a, T: ?Sized> {
mutex: &'a BfTermPool<T>,
locked: bool,
_marker: PhantomData<&'a ()>,
}
impl<T: ?Sized> BfTermPoolThreadWrite<'_, T> {
pub fn unlock(&mut self) -> bool {
if self.locked {
self.locked = false;
ffi::unlock_shared()
} else {
false
}
}
}
impl<T: ?Sized> Deref for BfTermPoolThreadWrite<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.object.get() }
}
}
impl<T: ?Sized> DerefMut for BfTermPoolThreadWrite<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mutex.object.get() }
}
}
impl<T: ?Sized> Drop for BfTermPoolThreadWrite<'_, T> {
fn drop(&mut self) {
if self.locked {
ffi::unlock_shared();
}
}
}