pub mod local_shared;
pub mod projected_shared;
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex, PoisonError};
use std::{cell::RefCell, rc::Rc};
pub use local_shared::LocalShared;
pub use projected_shared::ProjectedShared;
pub trait Shared: Clone {
type Target;
fn with<R, F>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self::Target) -> R;
fn project<To, Proj>(&self, f: Proj) -> ProjectedShared<Self, Proj>
where
Proj: Fn(&mut Self::Target) -> &mut To + Clone,
{
ProjectedShared {
inner: self.clone(),
proj_fn: f,
}
}
}
impl<T> Shared for Rc<RefCell<T>> {
type Target = T;
#[inline(always)]
fn with<R, F>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self::Target) -> R,
{
f(&mut self.borrow_mut())
}
}
impl<T> Shared for Arc<Mutex<T>> {
type Target = T;
#[inline(always)]
fn with<R, F>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self::Target) -> R,
{
f(&mut self.lock().unwrap_or_else(PoisonError::into_inner))
}
}
pub trait UnsafeShared: Clone {
type Target;
fn with<R, F>(&mut self, f: F) -> R
where
F: FnOnce(*mut Self::Target) -> R;
#[inline(always)]
unsafe fn with_unchecked<R, F>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self::Target) -> R,
{
self.with(move |t_ptr| f(unsafe { &mut *t_ptr }))
}
fn project<To, Proj>(&self, f: Proj) -> ProjectedShared<Self, Proj>
where
Proj: Fn(*mut Self::Target) -> *mut To + Clone,
{
ProjectedShared {
inner: self.clone(),
proj_fn: f,
}
}
}
impl<T> UnsafeShared for Rc<UnsafeCell<T>> {
type Target = T;
#[inline(always)]
fn with<R, F>(&mut self, f: F) -> R
where
F: FnOnce(*mut Self::Target) -> R,
{
f(self.get())
}
}
#[macro_export]
macro_rules! define_with {
($shared:expr) => {
macro_rules! with {
($f:expr) => {{
use $crate::shared::Shared;
$shared.with(
#[inline(always)]
$f,
)
}};
}
};
}
#[macro_export]
macro_rules! define_with_unchecked {
($shared:expr) => {
macro_rules! with_unchecked {
($f:expr) => {{
use $crate::shared::UnsafeShared;
$shared.with_unchecked(
#[inline(always)]
$f,
)
}};
}
};
}