use std::cell::UnsafeCell;
use std::ptr;
use crate::simulation;
use crate::simulation::point::Point;
use crate::simulation::event::Event;
use dvcompute_utils::grc::Grc;
pub struct RefComp<T> {
cell: UnsafeCell<T>
}
impl<T> RefComp<T> {
#[inline]
pub fn new(val: T) -> RefComp<T> {
RefComp { cell: UnsafeCell::new(val) }
}
#[inline]
pub fn read_at(&self, _p: &Point) -> T
where T: Clone
{
let p = self.cell.get();
unsafe {
(*p).clone()
}
}
#[inline]
pub fn read(comp: Grc<Self>) -> Read<T>
where T: Clone
{
Read { comp: comp }
}
#[inline]
pub fn swap_at(&self, val: T, _p: &Point) -> T {
let mut t = val;
unsafe {
ptr::swap(&mut t, self.cell.get());
}
t
}
#[inline]
pub fn swap(comp: Grc<Self>, val: T) -> Swap<T> {
Swap { comp: comp, val: val }
}
#[inline]
pub fn write_at(&self, val: T, _p: &Point) {
let p = self.cell.get();
unsafe {
*p = val;
}
}
#[inline]
pub fn write(comp: Grc<Self>, val: T) -> Write<T> {
Write { comp: comp, val: val }
}
#[inline]
pub fn modify_at<F>(&self, f: F, _p: &Point)
where F: FnOnce(&T) -> T,
T: Clone
{
let p = self.cell.get();
unsafe {
let t = (*p).clone();
*p = f(&t);
}
}
#[inline]
pub fn modify<F>(comp: Grc<Self>, f: F) -> Modify<T, F>
where F: FnOnce(&T) -> T,
T: Clone
{
Modify { comp: comp, f: f }
}
}
impl<T> PartialEq for RefComp<T> {
fn eq(&self, other: &Self) -> bool {
self.cell.get() == other.cell.get()
}
}
impl<T> Eq for RefComp<T> {}
impl<T: Clone> Clone for RefComp<T> {
fn clone(&self) -> Self {
let p = self.cell.get();
unsafe {
let val = (*p).clone();
RefComp { cell: UnsafeCell::new(val) }
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Read<T> where T: 'static {
comp: Grc<RefComp<T>>
}
impl<T: Clone> Event for Read<T> {
type Item = T;
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Read { comp } = self;
Result::Ok(comp.read_at(p))
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Swap<T> where T: 'static {
comp: Grc<RefComp<T>>,
val: T
}
impl<T> Event for Swap<T> {
type Item = T;
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Swap { comp, val } = self;
Result::Ok(comp.swap_at(val, p))
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Write<T> where T: 'static {
comp: Grc<RefComp<T>>,
val: T
}
impl<T> Event for Write<T> {
type Item = ();
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Write { comp, val } = self;
Result::Ok(comp.write_at(val, p))
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Modify<T, F> where T: 'static {
comp: Grc<RefComp<T>>,
f: F
}
impl<T, F> Event for Modify<T, F>
where F: FnOnce(&T) -> T,
T: Clone
{
type Item = ();
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Modify { comp, f } = self;
Result::Ok(comp.modify_at(f, p))
}
}