use std::marker::PhantomData;
#[cfg(feature="cons_mode")]
use std::mem;
#[cfg(feature="cons_mode")]
use std::ptr;
#[cfg(feature="cons_mode")]
use libc::*;
use crate::simulation;
use crate::simulation::Point;
use crate::simulation::Run;
use crate::simulation::simulation::Simulation;
use crate::simulation::process::is_process_cancelled;
use crate::simulation::process::revoke_process;
use crate::simulation::process::revoke_process_boxed;
use crate::simulation::process::Process;
use crate::simulation::process::ProcessId;
use crate::simulation::process::ProcessBoxCont;
use crate::simulation::observable::disposable::*;
use crate::simulation::composite::*;
#[cfg(feature="cons_mode")]
use crate::simulation::error::*;
#[cfg(feature="cons_mode")]
use crate::simulation::internal::event_queue::*;
use dvcompute_utils::grc::Grc;
pub mod ops;
#[inline]
pub fn return_event<T>(val: T) -> Return<T> {
Return { val: val }
}
#[inline]
pub fn delay_event<F, M>(f: F) -> Delay<F, M>
where F: FnOnce() -> M,
M: Event
{
Delay { f: f, _phantom: PhantomData }
}
#[inline]
pub fn cons_event<F, T>(f: F) -> Cons<F, T>
where F: FnOnce(&Point) -> simulation::Result<T>
{
Cons { f: f, _phantom: PhantomData }
}
#[inline]
pub fn enqueue_event(time: f64, comp: EventBox<()>) -> Enqueue {
Enqueue { time: time, comp: comp }
}
#[inline]
pub fn enqueue_event_with_priority(time: f64, priority: isize, comp: EventBox<()>) -> EnqueueWithPriority {
EnqueueWithPriority { time: time, priority: priority, comp: comp }
}
#[inline]
pub fn enqueue_events_with_integ_times<F>(f: F) -> EnqueueWithIntegTimes<F>
where F: Fn() -> EventBox<()> + 'static
{
EnqueueWithIntegTimes { f: f }
}
#[inline]
pub fn enqueue_io_event(time: f64, comp: EventBox<()>) -> EnqueueIO {
EnqueueIO { time: time, comp: comp }
}
#[inline]
pub fn enqueue_io_event_with_priority(time: f64, priority: isize, comp: EventBox<()>) -> EnqueueIOWithPriority {
EnqueueIOWithPriority { time: time, priority: priority, comp: comp }
}
#[inline]
pub fn enqueue_io_events_with_integ_times<F>(f: F) -> EnqueueIOWithIntegTimes<F>
where F: Fn() -> EventBox<()> + 'static
{
EnqueueIOWithIntegTimes { f: f }
}
#[inline]
pub fn yield_event<M>(comp: M) -> Yield<M>
where M: Event<Item = ()> + 'static
{
Yield { comp: comp }
}
#[inline]
pub fn time_event() -> Time {
Time {}
}
#[inline]
pub fn priority_event() -> Priority {
Priority {}
}
#[inline]
pub fn event_sequence<I, M>(comps: I) -> Sequence<I::IntoIter, M>
where I: IntoIterator<Item = M>,
M: Event
{
Sequence { comps: comps.into_iter(), _phantom: PhantomData }
}
#[inline]
pub fn event_sequence_<I, M>(comps: I) -> Sequence_<I::IntoIter, M>
where I: IntoIterator<Item = M>,
M: Event
{
Sequence_ { comps: comps.into_iter(), _phantom: PhantomData }
}
#[inline]
pub fn trace_event<M>(msg: String, comp: M) -> Trace<M>
where M: Event
{
Trace { comp: comp, msg: msg}
}
pub trait Event {
type Item;
#[doc(hidden)]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item>;
fn into_process(self) -> EventIntoProcess<Self>
where Self: Sized
{
EventIntoProcess { comp: self }
}
fn into_composite(self) -> EventIntoComposite<Self>
where Self: Sized
{
EventIntoComposite { comp: self }
}
#[inline]
fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
where Self: Sized,
U: Event,
F: FnOnce(Self::Item) -> U,
{
AndThen { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn map<B, F>(self, f: F) -> Map<Self, B, F>
where Self: Sized,
F: FnOnce(Self::Item) -> B,
{
Map { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn zip<U>(self, other: U) -> Zip<Self, U>
where Self: Sized,
U: Event
{
Zip { comp: self, other: other }
}
#[inline]
fn ap<U, B>(self, other: U) -> Ap<Self, U, B>
where Self: Sized,
Self::Item: FnOnce(U::Item) -> B,
U: Event
{
Ap { comp: self, other: other, _phantom: PhantomData }
}
#[inline]
fn run_in_start_time(self) -> RunInStartTime<Self>
where Self: Sized
{
RunInStartTime { comp: self, including_current_events: true }
}
#[inline]
fn run_in_start_time_by(self, including_current_events: bool) -> RunInStartTime<Self>
where Self: Sized
{
RunInStartTime { comp: self, including_current_events: including_current_events }
}
#[inline]
fn run_in_stop_time(self) -> RunInStopTime<Self>
where Self: Sized
{
RunInStopTime { comp: self, including_current_events: true }
}
#[inline]
fn run_in_stop_time_by(self, including_current_events: bool) -> RunInStopTime<Self>
where Self: Sized
{
RunInStopTime { comp: self, including_current_events: including_current_events }
}
#[inline]
fn into_boxed(self) -> EventBox<Self::Item>
where Self: Sized + 'static
{
EventBox::new(move |p: &Point| { self.call_event(p) })
}
}
pub trait IntoEvent {
type Event: Event<Item = Self::Item>;
type Item;
fn into_event(self) -> Self::Event;
}
impl<M: Event> IntoEvent for M {
type Event = M;
type Item = M::Item;
#[inline]
fn into_event(self) -> Self::Event {
self
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct EventBox<T> {
f: Box<dyn EventFnBox<T>>
}
impl<T> EventBox<T> {
#[doc(hidden)]
#[inline]
fn new<F>(f: F) -> Self
where F: FnOnce(&Point) -> simulation::Result<T> + 'static
{
EventBox {
f: Box::new(f)
}
}
#[doc(hidden)]
#[inline]
pub fn call_box(self, arg: (&Point,)) -> simulation::Result<T> {
let EventBox { f } = self;
f.call_box(arg)
}
}
impl<T> Event for EventBox<T> {
type Item = T;
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
self.call_box((p,))
}
#[inline]
fn into_boxed(self) -> EventBox<Self::Item>
where Self: Sized + 'static
{
self
}
}
trait EventFnBox<T> {
fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<T>;
}
impl<T, F> EventFnBox<T> for F
where F: for<'a> FnOnce(&'a Point) -> simulation::Result<T>
{
fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<T> {
let this: Self = *self;
this(args.0)
}
}
#[cfg(feature="cons_mode")]
#[repr(C)]
#[derive(Copy, Clone)]
struct EventTraitObject {
field1: *mut c_void,
field2: *mut c_void
}
#[cfg(feature="cons_mode")]
#[repr(C)]
pub struct EventRepr {
delete: unsafe extern "C" fn(obj: *mut EventTraitObject),
callback: unsafe extern "C" fn(obj: *mut EventTraitObject, p: *const Point) -> *mut ErrorRepr,
trait_object: EventTraitObject
}
#[cfg(feature="cons_mode")]
impl Drop for EventRepr {
fn drop(&mut self) {
unsafe {
(self.delete)(&mut self.trait_object);
}
}
}
#[cfg(feature="cons_mode")]
impl EventRepr {
#[inline]
pub fn into_repr(comp: EventBox<()>) -> EventRepr {
unsafe {
EventRepr {
delete: delete_event_repr,
callback: call_event_repr,
trait_object: mem::transmute(comp)
}
}
}
#[inline]
fn call_repr(mut self, p: &Point) -> *mut ErrorRepr {
unsafe {
let x = (self.callback)(&mut self.trait_object, p);
mem::forget(self);
x
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn call_event_repr(comp: *mut EventTraitObject, p: *const Point) -> *mut ErrorRepr {
let comp: EventBox<()> = mem::transmute(*comp);
match comp.call_box((&*p,)) {
Result::Ok(()) => ptr::null_mut(),
Result::Err(e) => {
let e = ErrorRepr::new(e);
Box::into_raw(Box::new(e))
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn delete_event_repr(comp: *mut EventTraitObject) {
let _: EventBox<()> = mem::transmute(*comp);
}
#[cfg(feature="cons_mode")]
impl Event for EventRepr {
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
unsafe {
let e = self.call_repr(p);
if e == ptr::null_mut() {
Result::Ok(())
} else {
let e = ffi_error_repr_into_error(e);
Result::Err(e)
}
}
}
}
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
pub struct EventRepr {
comp: EventBox<()>
}
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
impl EventRepr {
#[inline]
pub fn into_repr(comp: EventBox<()>) -> EventRepr {
EventRepr { comp: comp }
}
#[inline]
fn call_repr(self, p: &Point) -> simulation::Result<()> {
self.comp.call_event(p)
}
}
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
impl Event for EventRepr {
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
self.call_repr(p)
}
}
#[cfg(feature="cons_mode")]
#[repr(C)]
#[derive(Copy, Clone)]
struct DisposableEventTraitObject {
field1: *mut c_void,
field2: *mut c_void
}
#[cfg(feature="cons_mode")]
#[repr(C)]
pub struct DisposableEventRepr {
delete: unsafe extern "C" fn(obj: *mut DisposableEventTraitObject),
callback: unsafe extern "C" fn(obj: *mut DisposableEventTraitObject, p: *const Point, e: *mut *mut ErrorRepr) -> DisposableRepr,
trait_object: DisposableEventTraitObject
}
#[cfg(feature="cons_mode")]
impl Drop for DisposableEventRepr {
fn drop(&mut self) {
unsafe {
(self.delete)(&mut self.trait_object);
}
}
}
#[cfg(feature="cons_mode")]
impl DisposableEventRepr {
#[inline]
pub fn into_repr(comp: EventBox<DisposableRepr>) -> DisposableEventRepr {
unsafe {
DisposableEventRepr {
delete: delete_disposable_event_repr,
callback: call_disposable_event_repr,
trait_object: mem::transmute(comp)
}
}
}
#[inline]
fn call_repr(mut self, p: &Point, e: *mut *mut ErrorRepr) -> DisposableRepr {
unsafe {
let x = (self.callback)(&mut self.trait_object, p, e);
mem::forget(self);
x
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn call_disposable_event_repr(comp: *mut DisposableEventTraitObject, p: *const Point, e: *mut *mut ErrorRepr) -> DisposableRepr {
let comp: EventBox<DisposableRepr> = mem::transmute(*comp);
match comp.call_box((&*p,)) {
Result::Ok(x) => {
*e = ptr::null_mut();
x
},
Result::Err(e0) => {
let e0 = ErrorRepr::new(e0);
let e0 = Box::new(e0);
let e0 = Box::into_raw(e0);
*e = e0;
let x = empty_disposable();
let x = x.into_boxed();
let x = DisposableRepr::into_repr(x);
x
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn delete_disposable_event_repr(comp: *mut DisposableEventTraitObject) {
let _: EventBox<DisposableRepr> = mem::transmute(*comp);
}
#[cfg(feature="cons_mode")]
impl Event for DisposableEventRepr {
type Item = DisposableRepr;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
unsafe {
let mut e: *mut ErrorRepr = ptr::null_mut();
let x = self.call_repr(p, &mut e);
if e == ptr::null_mut() {
Result::Ok(x)
} else {
let e = ffi_error_repr_into_error(e);
Result::Err(e)
}
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Return<T> {
val: T
}
impl<T> Event for Return<T> {
type Item = T;
#[doc(hidden)]
#[inline]
fn call_event(self, _: &Point) -> simulation::Result<T> {
let Return { val } = self;
Result::Ok(val)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Delay<F, M> {
f: F,
_phantom: PhantomData<M>
}
impl<F, M> Event for Delay<F, M>
where F: FnOnce() -> M,
M: Event
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<M::Item> {
let Delay { f, _phantom } = self;
f().call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Cons<F, T> {
f: F,
_phantom: PhantomData<T>
}
impl<F, T> Event for Cons<F, T>
where F: FnOnce(&Point) -> simulation::Result<T>
{
type Item = T;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<T> {
let Cons { f, _phantom } = self;
f(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct Enqueue {
time: f64,
comp: EventBox<()>
}
impl Event for Enqueue {
type Item = ();
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let Enqueue { time, comp } = self;
let run = p.run;
let queue = &run.event_queue;
let comp = EventRepr::into_repr(comp);
queue.enqueue_event(time, p.priority, comp, p);
Result::Ok(())
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let Enqueue { time, comp } = self;
let run = p.run;
let queue = run.event_queue;
let comp = EventRepr::into_repr(comp);
unsafe {
enqueue_extern_event(queue, time, p.priority, comp, p);
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct EnqueueWithPriority {
time: f64,
priority: isize,
comp: EventBox<()>
}
impl Event for EnqueueWithPriority {
type Item = ();
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueWithPriority { time, priority, comp } = self;
let run = p.run;
let queue = &run.event_queue;
let comp = EventRepr::into_repr(comp);
queue.enqueue_event(time, priority, comp, p);
Result::Ok(())
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueWithPriority { time, priority, comp } = self;
let run = p.run;
let queue = run.event_queue;
let comp = EventRepr::into_repr(comp);
unsafe {
enqueue_extern_event(queue, time, priority, comp, p);
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct EnqueueWithIntegTimes<F> {
f: F
}
impl<F> Event for EnqueueWithIntegTimes<F>
where F: Fn() -> EventBox<()> + 'static
{
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueWithIntegTimes { f } = self;
let n = p.iteration;
let p2 = p.with_iteration(n);
let b = p2.time < p.time;
let n3 = if b { 1 + n } else { n };
let p3 = if b { p.with_iteration(n3) } else { p2 };
let comp = EnqueueWithIntegTimesLoop { f, iteration: p3.iteration };
enqueue_event(p3.time, comp.into_boxed())
.call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
struct EnqueueWithIntegTimesLoop<F> {
f: F,
iteration: usize
}
impl<F> Event for EnqueueWithIntegTimesLoop<F>
where F: Fn() -> EventBox<()> + 'static
{
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueWithIntegTimesLoop { f, iteration } = self;
let comp = f();
comp.call_event(&p)?;
let p2 = p.with_iteration(1 + iteration);
let comp = EnqueueWithIntegTimesLoop { f, iteration: p2.iteration };
enqueue_event(p2.time, comp.into_boxed())
.call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct EnqueueIO {
time: f64,
comp: EventBox<()>
}
impl Event for EnqueueIO {
type Item = ();
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIO { time, comp } = self;
let run = p.run;
let queue = &run.event_queue;
let comp = EventRepr::into_repr(comp);
queue.enqueue_io_event(time, p.priority, comp, p);
Result::Ok(())
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIO { time, comp } = self;
let run = p.run;
let queue = run.event_queue;
let comp = EventRepr::into_repr(comp);
unsafe {
enqueue_extern_io_event(queue, time, p.priority, comp, p);
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct EnqueueIOWithPriority {
time: f64,
priority: isize,
comp: EventBox<()>
}
impl Event for EnqueueIOWithPriority {
type Item = ();
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIOWithPriority { time, priority, comp } = self;
let run = p.run;
let queue = &run.event_queue;
let comp = EventRepr::into_repr(comp);
queue.enqueue_io_event(time, priority, comp, p);
Result::Ok(())
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIOWithPriority { time, priority, comp } = self;
let run = p.run;
let queue = run.event_queue;
let comp = EventRepr::into_repr(comp);
unsafe {
enqueue_extern_io_event(queue, time, priority, comp, p);
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct EnqueueIOWithIntegTimes<F> {
f: F
}
impl<F> Event for EnqueueIOWithIntegTimes<F>
where F: Fn() -> EventBox<()> + 'static
{
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIOWithIntegTimes { f } = self;
let n = p.iteration;
let p2 = p.with_iteration(n);
let b = p2.time < p.time;
let n3 = if b { 1 + n } else { n };
let p3 = if b { p.with_iteration(n3) } else { p2 };
let comp = EnqueueIOWithIntegTimesLoop { f, iteration: p3.iteration };
enqueue_io_event(p3.time, comp.into_boxed())
.call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
struct EnqueueIOWithIntegTimesLoop<F> {
f: F,
iteration: usize
}
impl<F> Event for EnqueueIOWithIntegTimesLoop<F>
where F: Fn() -> EventBox<()> + 'static
{
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<()> {
let EnqueueIOWithIntegTimesLoop { f, iteration } = self;
let comp = f();
comp.call_event(&p)?;
let p2 = p.with_iteration(1 + iteration);
let comp = EnqueueIOWithIntegTimesLoop { f, iteration: p2.iteration };
enqueue_io_event(p2.time, comp.into_boxed())
.call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct AndThen<M, U, F> {
comp: M,
f: F,
_phantom: PhantomData<U>
}
impl<M, U, F> Event for AndThen<M, U, F>
where M: Event,
U: Event,
F: FnOnce(M::Item) -> U,
{
type Item = U::Item;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<U::Item> {
let AndThen { comp, f, _phantom } = self;
match comp.call_event(p) {
Result::Ok(a) => {
let m = f(a);
m.call_event(p)
},
Result::Err(e) => {
Result::Err(e)
}
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Map<M, B, F> {
comp: M,
f: F,
_phantom: PhantomData<B>
}
impl<M, B, F> Event for Map<M, B, F>
where M: Event,
F: FnOnce(M::Item) -> B,
{
type Item = B;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<B> {
let Map { comp, f, _phantom } = self;
match comp.call_event(p) {
Result::Ok(a) => Result::Ok(f(a)),
Result::Err(e) => Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Zip<M, U> {
comp: M,
other: U,
}
impl<M, U> Event for Zip<M, U>
where M: Event,
U: Event
{
type Item = (M::Item, U::Item);
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<(M::Item, U::Item)> {
let Zip { comp, other } = self;
comp.and_then(move |a| {
other.map(move |b| (a, b))
}).call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Ap<M, U, B> {
comp: M,
other: U,
_phantom: PhantomData<B>
}
impl<M, U, B> Event for Ap<M, U, B>
where M: Event,
U: Event,
M::Item: FnOnce(U::Item) -> B,
{
type Item = B;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<B> {
let Ap { comp, other, _phantom } = self;
comp.and_then(move |f| {
other.map(move |a| { f(a) })
}).call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct RunInStartTime<M> {
comp: M,
including_current_events: bool
}
impl<M> Simulation for RunInStartTime<M>
where M: Event
{
type Item = M::Item;
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
let RunInStartTime { comp, including_current_events } = self;
let p = r.point_in_start_time();
let queue = &r.event_queue;
queue.run_events(including_current_events, &p)?;
comp.call_event(&p)
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
let RunInStartTime { comp, including_current_events } = self;
let p = r.point_in_start_time();
let including_current_events = if including_current_events { 1 } else { 0 };
let e = unsafe {
run_extern_events(including_current_events, &p)
};
if e == ptr::null_mut() {
comp.call_event(&p)
} else {
let e = unsafe {
ffi_error_repr_into_error(e)
};
Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct RunInStopTime<M> {
comp: M,
including_current_events: bool
}
impl<M> Simulation for RunInStopTime<M>
where M: Event
{
type Item = M::Item;
#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
#[doc(hidden)]
#[inline]
fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
let RunInStopTime { comp, including_current_events } = self;
let p = r.point_in_stop_time();
let queue = &r.event_queue;
queue.run_events(including_current_events, &p)?;
comp.call_event(&p)
}
#[cfg(feature="cons_mode")]
#[doc(hidden)]
#[inline]
fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
let RunInStopTime { comp, including_current_events } = self;
let p = r.point_in_stop_time();
let including_current_events = if including_current_events { 1 } else { 0 };
let e = unsafe {
run_extern_events(including_current_events, &p)
};
if e == ptr::null_mut() {
comp.call_event(&p)
} else {
let e = unsafe {
ffi_error_repr_into_error(e)
};
Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Time {}
impl Event for Time {
type Item = f64;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<f64> {
Result::Ok(p.time)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Priority {}
impl Event for Priority {
type Item = isize;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<isize> {
Result::Ok(p.priority)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct EventIntoProcess<M> {
comp: M
}
impl<M> Process for EventIntoProcess<M>
where M: Event
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_process<C>(self, cont: C, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()>
where C: FnOnce(simulation::Result<Self::Item>, Grc<ProcessId>, &Point) -> simulation::Result<()> + 'static
{
if is_process_cancelled(&pid, p) {
revoke_process(cont, pid, p)
} else {
let EventIntoProcess { comp } = self;
let t = comp.call_event(p);
cont(t, pid, p)
}
}
#[doc(hidden)]
#[inline]
fn call_process_boxed(self, cont: ProcessBoxCont<Self::Item>, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()> {
if is_process_cancelled(&pid, p) {
revoke_process_boxed(cont, pid, p)
} else {
let EventIntoProcess { comp } = self;
let t = comp.call_event(p);
cont.call_box((t, pid, p))
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct EventIntoComposite<M> {
comp: M
}
impl<M> Composite for EventIntoComposite<M>
where M: Event
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(M::Item, DisposableBox)> {
let EventIntoComposite { comp } = self;
let a = comp.call_event(p)?;
Result::Ok((a, disposable))
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Sequence<I, M> {
comps: I,
_phantom: PhantomData<M>
}
impl<I, M> Event for Sequence<I, M>
where I: Iterator<Item = M>,
M: Event
{
type Item = Vec<M::Item>;
#[doc(hidden)]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Sequence { comps, _phantom } = self;
let mut v = {
match comps.size_hint() {
(_, Some(n)) => Vec::with_capacity(n),
(_, None) => Vec::new()
}
};
for m in comps {
match m.call_event(p) {
Result::Ok(a) => {
v.push(a)
},
Result::Err(e) => {
return Result::Err(e)
}
}
}
Result::Ok(v)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Sequence_<I, M> {
comps: I,
_phantom: PhantomData<M>
}
impl<I, M> Event for Sequence_<I, M>
where I: Iterator<Item = M>,
M: Event
{
type Item = ();
#[doc(hidden)]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Sequence_ { comps, _phantom } = self;
for m in comps {
match m.call_event(p) {
Result::Ok(_) => (),
Result::Err(e) => return Result::Err(e)
}
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Yield<M> {
comp: M
}
impl<M> Event for Yield<M>
where M: Event<Item = ()> + 'static
{
type Item = ();
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Yield { comp } = self;
enqueue_event(p.time, comp.into_boxed()).call_event(p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Trace<M> {
comp: M,
msg: String
}
impl<M> Event for Trace<M>
where M: Event
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
let Trace { comp, msg } = self;
p.trace(&msg);
comp.call_event(p)
}
}