dvcompute_branch/simulation/event/
mod.rs

1// Copyright (c) 2020-2022  David Sorokin <davsor@mail.ru>, based in Yoshkar-Ola, Russia
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::marker::PhantomData;
8
9#[cfg(feature="dist_mode")]
10use std::mem;
11
12#[cfg(feature="dist_mode")]
13use std::ptr;
14
15#[cfg(feature="dist_mode")]
16use libc::*;
17
18use crate::simulation;
19use crate::simulation::Point;
20use crate::simulation::Run;
21use crate::simulation::simulation::Simulation;
22use crate::simulation::process::is_process_cancelled;
23use crate::simulation::process::revoke_process;
24use crate::simulation::process::revoke_process_boxed;
25use crate::simulation::process::Process;
26use crate::simulation::process::ProcessId;
27use crate::simulation::process::ProcessBoxCont;
28use crate::simulation::observable::disposable::*;
29use crate::simulation::composite::*;
30
31#[cfg(feature="dist_mode")]
32use crate::simulation::error::*;
33
34#[cfg(feature="dist_mode")]
35use crate::simulation::internal::event_queue::*;
36
37use dvcompute_utils::grc::Grc;
38
39/// Additional operations.
40pub mod ops;
41
42/// Return a new `Event` computation by the specified pure value.
43#[inline]
44pub fn return_event<T>(val: T) -> Return<T> {
45    Return { val: val }
46}
47
48/// Delay the `Event` computation.
49#[inline]
50pub fn delay_event<F, M>(f: F) -> Delay<F, M>
51    where F: FnOnce() -> M,
52          M: Event
53{
54    Delay { f: f, _phantom: PhantomData }
55}
56
57/// Construct a new `Event` computation by the specified function.
58#[inline]
59pub fn cons_event<F, T>(f: F) -> Cons<F, T>
60    where F: FnOnce(&Point) -> simulation::Result<T>
61{
62     Cons { f: f, _phantom: PhantomData }
63}
64
65/// Enqueue an event which handler should be activated at the specified time.
66#[inline]
67pub fn enqueue_event(time: f64, comp: EventBox<()>) -> Enqueue {
68    Enqueue { time: time, comp: comp }
69}
70
71/// Enqueue an event which handler should be activated at the specified time with the given priority.
72#[inline]
73pub fn enqueue_event_with_priority(time: f64, priority: isize, comp: EventBox<()>) -> EnqueueWithPriority {
74    EnqueueWithPriority { time: time, priority: priority, comp: comp }
75}
76
77/// Enqueue events which handlers should be activated in the integration time points.
78#[inline]
79pub fn enqueue_events_with_integ_times<F>(f: F) -> EnqueueWithIntegTimes<F>
80    where F: Fn() -> EventBox<()> + Clone + 'static
81{
82    EnqueueWithIntegTimes { f: f }
83}
84
85/// Enqueue an IO-based event which handler should be activated at the specified time.
86#[inline]
87pub fn enqueue_io_event(time: f64, comp: EventBox<()>) -> EnqueueIO {
88    EnqueueIO { time: time, comp: comp }
89}
90
91/// Enqueue an IO-based event which handler should be activated at the specified time with the given priority.
92#[inline]
93pub fn enqueue_io_event_with_priority(time: f64, priority: isize, comp: EventBox<()>) -> EnqueueIOWithPriority {
94    EnqueueIOWithPriority { time: time, priority: priority, comp: comp }
95}
96
97/// Enqueue IO-based events which handlers should be activated in the integration time points.
98#[inline]
99pub fn enqueue_io_events_with_integ_times<F>(f: F) -> EnqueueIOWithIntegTimes<F>
100    where F: Fn() -> EventBox<()> + Clone + 'static
101{
102    EnqueueIOWithIntegTimes { f: f }
103}
104
105/// Enqueue the event which must be actuated with the current modeling time but later.
106#[inline]
107pub fn yield_event<M>(comp: M) -> Yield<M>
108    where M: Event<Item = ()> + Clone + 'static
109{
110    Yield { comp: comp }
111}
112
113/// Return the current modeling time.
114#[inline]
115pub fn time_event() -> Time {
116    Time {}
117}
118
119/// Return the current modeling time priority.
120#[inline]
121pub fn priority_event() -> Priority {
122    Priority {}
123}
124
125/// Create a sequence of computations.
126#[inline]
127pub fn event_sequence<I, M>(comps: I) -> Sequence<I::IntoIter, M>
128    where I: IntoIterator<Item = M>,
129          M: Event
130{
131    Sequence { comps: comps.into_iter(), _phantom: PhantomData }
132}
133
134/// Create a sequence of computations, where the result is ignored.
135#[inline]
136pub fn event_sequence_<I, M>(comps: I) -> Sequence_<I::IntoIter, M>
137    where I: IntoIterator<Item = M>,
138          M: Event
139{
140    Sequence_ { comps: comps.into_iter(), _phantom: PhantomData }
141}
142
143/// Trace the computation.
144#[inline]
145pub fn trace_event<M>(msg: String, comp: M) -> Trace<M>
146    where M: Event
147{
148    Trace { comp: comp, msg: msg}
149}
150
151/// Try to leave the simulation.
152///
153/// It enqueues a new event with obligatory synchronization with the global virtual time.
154/// If that event will not be reverted during rollback, then the logical process will
155/// leave the simulation immediately after approaching the final modeling time without
156/// synchronization with the global virtual time anymore if it has no unacknowledged
157/// sent messages.
158///
159/// It makes sense to use this action if logical processes can enter and leave your long-running
160/// distributed simulation by demand.
161#[cfg(feature="dist_mode")]
162#[inline]
163pub fn leave_simulation() -> LeaveSimulation {
164    LeaveSimulation {}
165}
166
167/// The computation synchronized with the event queue.
168pub trait Event {
169
170    /// The type of the item that is returned in the current modeling time.
171    type Item;
172
173    /// Call the `Event` computation in the current modeling time.
174    #[doc(hidden)]
175    fn call_event(self, p: &Point) -> simulation::Result<Self::Item>;
176
177    /// Convert to the `Process` computation.
178    fn into_process(self) -> EventIntoProcess<Self>
179        where Self: Sized
180    {
181        EventIntoProcess { comp: self }
182    }
183
184    /// Convert to the `Composite` computation.
185    fn into_composite(self) -> EventIntoComposite<Self>
186        where Self: Sized
187    {
188        EventIntoComposite { comp: self }
189    }
190
191    /// Bind the current computation with its continuation within the resulting computation.
192    #[inline]
193    fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
194        where Self: Sized,
195              U: Event,
196              F: FnOnce(Self::Item) -> U,
197    {
198        AndThen { comp: self, f: f, _phantom: PhantomData }
199    }
200
201    /// Map the current computation using the specified transform.
202    #[inline]
203    fn map<B, F>(self, f: F) -> Map<Self, B, F>
204        where Self: Sized,
205              F: FnOnce(Self::Item) -> B,
206    {
207        Map { comp: self, f: f, _phantom: PhantomData }
208    }
209
210    /// Zip the current computation with another one within the resulting computation.
211    #[inline]
212    fn zip<U>(self, other: U) -> Zip<Self, U>
213        where Self: Sized,
214              U: Event
215    {
216        Zip { comp: self, other: other }
217    }
218
219    /// The function application.
220    #[inline]
221    fn ap<U, B>(self, other: U) -> Ap<Self, U, B>
222        where Self: Sized,
223              Self::Item: FnOnce(U::Item) -> B,
224              U: Event
225    {
226        Ap { comp: self, other: other, _phantom: PhantomData }
227    }
228
229    /// Run the computation in the start time.
230    #[inline]
231    fn run_in_start_time(self) -> RunInStartTime<Self>
232        where Self: Sized
233    {
234        RunInStartTime { comp: self, including_current_events: true }
235    }
236
237    /// Run the computation in the start time by processing the current events or not.
238    #[inline]
239    fn run_in_start_time_by(self, including_current_events: bool) -> RunInStartTime<Self>
240        where Self: Sized
241    {
242        RunInStartTime { comp: self, including_current_events: including_current_events }
243    }
244
245    /// Run the computation in the stop time.
246    #[inline]
247    fn run_in_stop_time(self) -> RunInStopTime<Self>
248        where Self: Sized
249    {
250        RunInStopTime { comp: self, including_current_events: true }
251    }
252
253    /// Run the computation in the stop time by processing the current events or not.
254    #[inline]
255    fn run_in_stop_time_by(self, including_current_events: bool) -> RunInStopTime<Self>
256        where Self: Sized
257    {
258        RunInStopTime { comp: self, including_current_events: including_current_events }
259    }
260
261    /// Convert into a boxed value.
262    #[inline]
263    fn into_boxed(self) -> EventBox<Self::Item>
264        where Self: Sized + Clone + 'static
265    {
266        EventBox::new(move |p: &Point| { self.call_event(p) })
267    }
268}
269
270/// Allows converting to `Event` computations.
271pub trait IntoEvent {
272
273    /// The target computation.
274    type Event: Event<Item = Self::Item>;
275
276    /// The type of item that is returned by the computation.
277    type Item;
278
279    /// Convert to the `Event` computation.
280    fn into_event(self) -> Self::Event;
281}
282
283impl<M: Event> IntoEvent for M {
284
285    type Event = M;
286
287    type Item = M::Item;
288
289    #[inline]
290    fn into_event(self) -> Self::Event {
291        self
292    }
293}
294
295/// It represents the boxed `Event` computation.
296#[must_use = "computations are lazy and do nothing unless to be run"]
297pub struct EventBox<T> {
298    f: Box<dyn EventFnBoxClone<T>>
299}
300
301impl<T> EventBox<T> {
302
303    /// Create a new boxed computation.
304    #[doc(hidden)]
305    #[inline]
306    fn new<F>(f: F) -> Self
307        where F: FnOnce(&Point) -> simulation::Result<T> + Clone + 'static
308    {
309        EventBox {
310            f: Box::new(f)
311        }
312    }
313
314    /// Call the boxed function.
315    #[doc(hidden)]
316    #[inline]
317    pub fn call_box(self, arg: (&Point,)) -> simulation::Result<T> {
318        let EventBox { f } = self;
319        f.call_box(arg)
320    }
321}
322
323impl<T> Clone for EventBox<T> {
324
325    fn clone(&self) -> Self {
326        EventBox {
327            f: self.f.call_clone()
328        }
329    }
330}
331
332impl<T> Event for EventBox<T> {
333
334    type Item = T;
335
336    #[inline]
337    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
338        self.call_box((p,))
339    }
340
341    #[inline]
342    fn into_boxed(self) -> EventBox<Self::Item>
343        where Self: Sized + Clone + 'static
344    {
345        self
346    }
347}
348
349/// A trait to support the stable version of Rust, where there is no `FnBox`.
350trait EventFnBox<T> {
351
352    /// Call the corresponding function.
353    fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<T>;
354}
355
356impl<T, F> EventFnBox<T> for F
357    where F: for<'a> FnOnce(&'a Point) -> simulation::Result<T>
358{
359    fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<T> {
360        let this: Self = *self;
361        this(args.0)
362    }
363}
364
365/// A trait to implement a cloneable `FnBox`.
366trait EventFnBoxClone<T>: EventFnBox<T> {
367
368    /// Clone the function.
369    fn call_clone(&self) -> Box<dyn EventFnBoxClone<T>>;
370}
371
372impl<T, F> EventFnBoxClone<T> for F
373    where F: for<'a> FnOnce(&'a Point) -> simulation::Result<T> + Clone + 'static
374{
375    fn call_clone(&self) -> Box<dyn EventFnBoxClone<T>> {
376        Box::new(self.clone())
377    }
378}
379
380/// It represents a raw trait object.
381#[cfg(feature="dist_mode")]
382#[repr(C)]
383#[derive(Copy, Clone)]
384struct EventTraitObject {
385
386    field1: *mut c_void,
387    field2: *mut c_void
388}
389
390/// A C-friendly representaton of the `Event` action.
391#[cfg(feature="dist_mode")]
392#[repr(C)]
393pub struct EventRepr {
394
395    /// Delete the object.
396    delete: unsafe extern "C" fn(obj: *mut EventTraitObject),
397
398    /// Clone the action.
399    clone: unsafe extern "C" fn(obj: *const EventTraitObject) -> EventRepr,
400
401    /// The callback.
402    callback: unsafe extern "C" fn(obj: *mut EventTraitObject, p: *const Point) -> *mut ErrorRepr,
403
404    /// The trait object.
405    trait_object: EventTraitObject
406}
407
408#[cfg(feature="dist_mode")]
409impl Drop for EventRepr {
410
411    fn drop(&mut self) {
412        unsafe {
413            (self.delete)(&mut self.trait_object);
414        }
415    }
416}
417
418#[cfg(feature="dist_mode")]
419impl Clone for EventRepr {
420
421    fn clone(&self) -> Self {
422        unsafe {
423            (self.clone)(&self.trait_object)
424        }
425    }
426}
427
428#[cfg(feature="dist_mode")]
429impl EventRepr {
430
431    /// Convert to a C-friendly representation.
432    #[inline]
433    pub fn into_repr(comp: EventBox<()>) -> EventRepr {
434        unsafe {
435            EventRepr {
436                delete: delete_event_repr,
437                clone: clone_event_repr,
438                callback: call_event_repr,
439                trait_object: mem::transmute(comp)
440            }
441        }
442    }
443
444    /// Call the representation.
445    #[inline]
446    fn call_repr(mut self, p: &Point) -> *mut ErrorRepr {
447        unsafe {
448            let x = (self.callback)(&mut self.trait_object, p);
449            mem::forget(self);
450            x
451        }
452    }
453}
454
455/// Call the `EventBox` representation.
456#[cfg(feature="dist_mode")]
457unsafe extern "C" fn call_event_repr(comp: *mut EventTraitObject, p: *const Point) -> *mut ErrorRepr {
458    let comp: EventBox<()> = mem::transmute(*comp);
459    match comp.call_box((&*p,)) {
460        Result::Ok(()) => ptr::null_mut(),
461        Result::Err(e) => {
462            let e = ErrorRepr::new(e);
463            Box::into_raw(Box::new(e))
464        }
465    }
466}
467
468/// Clone the `EventBox` representation.
469#[cfg(feature="dist_mode")]
470unsafe extern "C" fn clone_event_repr(comp: *const EventTraitObject) -> EventRepr {
471    let comp: EventBox<()> = mem::transmute(*comp);
472    let x = EventRepr {
473        delete: delete_event_repr,
474        clone: clone_event_repr,
475        callback: call_event_repr,
476        trait_object: mem::transmute(comp.clone())
477    };
478    mem::forget(comp);
479    x
480}
481
482/// Delete the `EventBox` representation.
483#[cfg(feature="dist_mode")]
484unsafe extern "C" fn delete_event_repr(comp: *mut EventTraitObject) {
485    let _: EventBox<()> = mem::transmute(*comp);
486}
487
488#[cfg(feature="dist_mode")]
489impl Event for EventRepr {
490
491    type Item = ();
492
493    #[doc(hidden)]
494    #[inline]
495    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
496        unsafe {
497            let e = self.call_repr(p);
498            if e == ptr::null_mut() {
499                Result::Ok(())
500            } else {
501                let e = ffi_error_repr_into_error(e);
502                Result::Err(e)
503            }
504        }
505    }
506}
507
508/// A thin wrapper representaton of the `Event` action.
509#[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
510#[derive(Clone)]
511pub struct EventRepr {
512
513    /// The computation itself.
514    comp: EventBox<()>
515}
516
517#[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
518impl EventRepr {
519
520    /// Convert to the representation.
521    #[inline]
522    pub fn into_repr(comp: EventBox<()>) -> EventRepr {
523        EventRepr { comp: comp }
524    }
525
526    /// Call the representation.
527    #[inline]
528    fn call_repr(self, p: &Point) -> simulation::Result<()> {
529        self.comp.call_event(p)
530    }
531}
532
533#[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
534impl Event for EventRepr {
535
536    type Item = ();
537
538    #[doc(hidden)]
539    #[inline]
540    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
541        self.call_repr(p)
542    }
543}
544
545/// It represents a raw trait object.
546#[cfg(feature="dist_mode")]
547#[repr(C)]
548#[derive(Copy, Clone)]
549struct DisposableEventTraitObject {
550
551    field1: *mut c_void,
552    field2: *mut c_void
553}
554
555/// A C-friendly representaton of the `Event<DisposableBox>` computation.
556#[cfg(feature="dist_mode")]
557#[repr(C)]
558pub struct DisposableEventRepr {
559
560    /// Delete the object.
561    delete: unsafe extern "C" fn(obj: *mut DisposableEventTraitObject),
562
563    /// Clone the action.
564    clone: unsafe extern "C" fn(obj: *const DisposableEventTraitObject) -> DisposableEventRepr,
565
566    /// The callback.
567    callback: unsafe extern "C" fn(obj: *mut DisposableEventTraitObject, p: *const Point, e: *mut *mut ErrorRepr) -> DisposableRepr,
568
569    /// The trait object.
570    trait_object: DisposableEventTraitObject
571}
572
573#[cfg(feature="dist_mode")]
574impl Drop for DisposableEventRepr {
575
576    fn drop(&mut self) {
577        unsafe {
578            (self.delete)(&mut self.trait_object);
579        }
580    }
581}
582
583#[cfg(feature="dist_mode")]
584impl Clone for DisposableEventRepr {
585
586    fn clone(&self) -> Self {
587        unsafe {
588            (self.clone)(&self.trait_object)
589        }
590    }
591}
592
593#[cfg(feature="dist_mode")]
594impl DisposableEventRepr {
595
596    /// Convert to a C-friendly representation.
597    #[inline]
598    pub fn into_repr(comp: EventBox<DisposableRepr>) -> DisposableEventRepr {
599        unsafe {
600            DisposableEventRepr {
601                delete: delete_disposable_event_repr,
602                clone: clone_disposable_event_repr,
603                callback: call_disposable_event_repr,
604                trait_object: mem::transmute(comp)
605            }
606        }
607    }
608
609    /// Call the representation.
610    #[inline]
611    fn call_repr(mut self, p: &Point, e: *mut *mut ErrorRepr) -> DisposableRepr {
612        unsafe {
613            let x = (self.callback)(&mut self.trait_object, p, e);
614            mem::forget(self);
615            x
616        }
617    }
618}
619
620/// Call the `EventBox<DisposableRepr>` representation.
621#[cfg(feature="dist_mode")]
622unsafe extern "C" fn call_disposable_event_repr(comp: *mut DisposableEventTraitObject, p: *const Point, e: *mut *mut ErrorRepr) -> DisposableRepr {
623    let comp: EventBox<DisposableRepr> = mem::transmute(*comp);
624    match comp.call_box((&*p,)) {
625        Result::Ok(x) => {
626            *e = ptr::null_mut();
627            x
628        },
629        Result::Err(e0) => {
630            let e0 = ErrorRepr::new(e0);
631            let e0 = Box::new(e0);
632            let e0 = Box::into_raw(e0);
633            *e = e0;
634
635            let x = empty_disposable();
636            let x = x.into_boxed();
637            let x = DisposableRepr::into_repr(x);
638            x
639        }
640    }
641}
642
643/// Clone the `EventBox<DisposableRepr>` representation.
644#[cfg(feature="dist_mode")]
645unsafe extern "C" fn clone_disposable_event_repr(comp: *const DisposableEventTraitObject) -> DisposableEventRepr {
646    let comp: EventBox<DisposableRepr> = mem::transmute(*comp);
647    let x = DisposableEventRepr {
648        delete: delete_disposable_event_repr,
649        clone: clone_disposable_event_repr,
650        callback: call_disposable_event_repr,
651        trait_object: mem::transmute(comp.clone())
652    };
653    mem::forget(comp);
654    x
655}
656
657/// Delete the `EventBox<DisposableRepr>` representation.
658#[cfg(feature="dist_mode")]
659unsafe extern "C" fn delete_disposable_event_repr(comp: *mut DisposableEventTraitObject) {
660    let _: EventBox<DisposableRepr> = mem::transmute(*comp);
661}
662
663#[cfg(feature="dist_mode")]
664impl Event for DisposableEventRepr {
665
666    type Item = DisposableRepr;
667
668    #[doc(hidden)]
669    #[inline]
670    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
671        unsafe {
672            let mut e: *mut ErrorRepr = ptr::null_mut();
673            let x = self.call_repr(p, &mut e);
674            if e == ptr::null_mut() {
675                Result::Ok(x)
676            } else {
677                let e = ffi_error_repr_into_error(e);
678                Result::Err(e)
679            }
680        }
681    }
682}
683
684/// Allows creating the `Event` computation from a pure value.
685#[must_use = "computations are lazy and do nothing unless to be run"]
686#[derive(Clone)]
687pub struct Return<T> {
688
689    /// Return a pure value, which is then transformed to the computation.
690    val: T
691}
692
693impl<T> Event for Return<T> {
694
695    type Item = T;
696
697    #[doc(hidden)]
698    #[inline]
699    fn call_event(self, _: &Point) -> simulation::Result<T> {
700        let Return { val } = self;
701        Result::Ok(val)
702    }
703}
704
705/// Allows delaying the `Event` computation by the specified function.
706#[must_use = "computations are lazy and do nothing unless to be run"]
707#[derive(Clone)]
708pub struct Delay<F, M> {
709
710    /// Return the computation.
711    f: F,
712
713    /// To keep the type parameter.
714    _phantom: PhantomData<M>
715}
716
717impl<F, M> Event for Delay<F, M>
718    where F: FnOnce() -> M,
719          M: Event
720{
721    type Item = M::Item;
722
723    #[doc(hidden)]
724    #[inline]
725    fn call_event(self, p: &Point) -> simulation::Result<M::Item> {
726        let Delay { f, _phantom } = self;
727        f().call_event(p)
728    }
729}
730
731/// Allows constructing the `Event` computation by the specified function.
732#[must_use = "computations are lazy and do nothing unless to be run"]
733#[derive(Clone)]
734pub struct Cons<F, T> {
735
736    /// The function of time point.
737    f: F,
738
739    /// To keep the type parameter.
740    _phantom: PhantomData<T>
741}
742
743impl<F, T> Event for Cons<F, T>
744    where F: FnOnce(&Point) -> simulation::Result<T>
745{
746    type Item = T;
747
748    #[doc(hidden)]
749    #[inline]
750    fn call_event(self, p: &Point) -> simulation::Result<T> {
751        let Cons { f, _phantom } = self;
752        f(p)
753    }
754}
755
756/// Enqueues the event which handler should be actuated at the specified time.
757#[must_use = "computations are lazy and do nothing unless to be run"]
758#[derive(Clone)]
759pub struct Enqueue {
760
761    /// The time of activating the event.
762    time: f64,
763
764    /// The event handler.
765    comp: EventBox<()>
766}
767
768impl Event for Enqueue {
769
770    type Item = ();
771
772    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
773    #[doc(hidden)]
774    #[inline]
775    fn call_event(self, p: &Point) -> simulation::Result<()> {
776        let Enqueue { time, comp } = self;
777        let run   = p.run;
778        let queue = &run.event_queue;
779        let comp  = EventRepr::into_repr(comp);
780        queue.enqueue_event(time, p.priority, comp, p);
781        Result::Ok(())
782    }
783
784    #[cfg(feature="dist_mode")]
785    #[doc(hidden)]
786    #[inline]
787    fn call_event(self, p: &Point) -> simulation::Result<()> {
788        let Enqueue { time, comp } = self;
789        let run   = p.run;
790        let queue = run.event_queue;
791        let comp  = EventRepr::into_repr(comp);
792        unsafe {
793            enqueue_extern_event(queue, time, p.priority, comp, p);
794        }
795        Result::Ok(())
796    }
797}
798
799/// Enqueues the event which handler should be actuated at the specified time with the given priority.
800#[must_use = "computations are lazy and do nothing unless to be run"]
801pub struct EnqueueWithPriority {
802
803    /// The time of activating the event.
804    time: f64,
805
806    /// The time priority.
807    priority: isize,
808
809    /// The event handler.
810    comp: EventBox<()>
811}
812
813impl Event for EnqueueWithPriority {
814
815    type Item = ();
816
817    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
818    #[doc(hidden)]
819    #[inline]
820    fn call_event(self, p: &Point) -> simulation::Result<()> {
821        let EnqueueWithPriority { time, priority, comp } = self;
822        let run   = p.run;
823        let queue = &run.event_queue;
824        let comp  = EventRepr::into_repr(comp);
825        queue.enqueue_event(time, priority, comp, p);
826        Result::Ok(())
827    }
828
829    #[cfg(feature="dist_mode")]
830    #[doc(hidden)]
831    #[inline]
832    fn call_event(self, p: &Point) -> simulation::Result<()> {
833        let EnqueueWithPriority { time, priority, comp } = self;
834        let run   = p.run;
835        let queue = run.event_queue;
836        let comp  = EventRepr::into_repr(comp);
837        unsafe {
838            enqueue_extern_event(queue, time, priority, comp, p);
839        }
840        Result::Ok(())
841    }
842}
843
844/// Enqueues the events which handlers should be actuated in the integration time points.
845#[must_use = "computations are lazy and do nothing unless to be run"]
846#[derive(Clone)]
847pub struct EnqueueWithIntegTimes<F> {
848
849    /// The generator of event handlers.
850    f: F
851}
852
853impl<F> Event for EnqueueWithIntegTimes<F>
854    where F: Fn() -> EventBox<()> + Clone + 'static
855{
856    type Item = ();
857
858    #[doc(hidden)]
859    #[inline]
860    fn call_event(self, p: &Point) -> simulation::Result<()> {
861        let EnqueueWithIntegTimes { f } = self;
862        let comp = EnqueueWithIntegTimesLoop { f, iteration: p.iteration };
863        enqueue_event(p.time, comp.into_boxed())
864            .call_event(p)
865    }
866}
867
868/// Enqueues the events with the integration time points in a loop.
869#[must_use = "computations are lazy and do nothing unless to be run"]
870#[derive(Clone)]
871struct EnqueueWithIntegTimesLoop<F> {
872
873    /// The generator of event handlers.
874    f: F,
875
876    /// The iteration number.
877    iteration: usize
878}
879
880impl<F> Event for EnqueueWithIntegTimesLoop<F>
881    where F: Fn() -> EventBox<()> + Clone + 'static
882{
883    type Item = ();
884
885    #[doc(hidden)]
886    #[inline]
887    fn call_event(self, p: &Point) -> simulation::Result<()> {
888        let EnqueueWithIntegTimesLoop { f, iteration } = self;
889        let comp = f();
890        let p = p.with_iteration(iteration); // correction
891        comp.call_event(&p)?;
892        let p2 = p.with_iteration(1 + iteration);
893        let comp = EnqueueWithIntegTimesLoop { f, iteration: p2.iteration };
894        enqueue_event(p2.time, comp.into_boxed())
895            .call_event(&p)
896    }
897}
898
899/// Enqueues the IO-based event which handler should be actuated at the specified time.
900#[must_use = "computations are lazy and do nothing unless to be run"]
901pub struct EnqueueIO {
902
903    /// The time of activating the event.
904    time: f64,
905
906    /// The event handler.
907    comp: EventBox<()>
908}
909
910impl Event for EnqueueIO {
911
912    type Item = ();
913
914    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
915    #[doc(hidden)]
916    #[inline]
917    fn call_event(self, p: &Point) -> simulation::Result<()> {
918        let EnqueueIO { time, comp } = self;
919        let run   = p.run;
920        let queue = &run.event_queue;
921        let comp  = EventRepr::into_repr(comp);
922        queue.enqueue_io_event(time, p.priority, comp, p);
923        Result::Ok(())
924    }
925
926    #[cfg(feature="dist_mode")]
927    #[doc(hidden)]
928    #[inline]
929    fn call_event(self, p: &Point) -> simulation::Result<()> {
930        let EnqueueIO { time, comp } = self;
931        let run   = p.run;
932        let queue = run.event_queue;
933        let comp  = EventRepr::into_repr(comp);
934        unsafe {
935            enqueue_extern_io_event(queue, time, p.priority, comp, p);
936        }
937        Result::Ok(())
938    }
939}
940
941/// Enqueues the IO-based event which handler should be actuated at the specified time with the given priority.
942#[must_use = "computations are lazy and do nothing unless to be run"]
943pub struct EnqueueIOWithPriority {
944
945    /// The time of activating the event.
946    time: f64,
947
948    /// The time priority.
949    priority: isize,
950
951    /// The event handler.
952    comp: EventBox<()>
953}
954
955impl Event for EnqueueIOWithPriority {
956
957    type Item = ();
958
959    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
960    #[doc(hidden)]
961    #[inline]
962    fn call_event(self, p: &Point) -> simulation::Result<()> {
963        let EnqueueIOWithPriority { time, priority, comp } = self;
964        let run   = p.run;
965        let queue = &run.event_queue;
966        let comp  = EventRepr::into_repr(comp);
967        queue.enqueue_io_event(time, priority, comp, p);
968        Result::Ok(())
969    }
970
971    #[cfg(feature="dist_mode")]
972    #[doc(hidden)]
973    #[inline]
974    fn call_event(self, p: &Point) -> simulation::Result<()> {
975        let EnqueueIOWithPriority { time, priority, comp } = self;
976        let run   = p.run;
977        let queue = run.event_queue;
978        let comp  = EventRepr::into_repr(comp);
979        unsafe {
980            enqueue_extern_io_event(queue, time, priority, comp, p);
981        }
982        Result::Ok(())
983    }
984}
985
986/// Enqueues the IO-based events which handlers should be actuated in the integration time points.
987#[must_use = "computations are lazy and do nothing unless to be run"]
988#[derive(Clone)]
989pub struct EnqueueIOWithIntegTimes<F> {
990
991    /// The generator of event handlers.
992    f: F
993}
994
995impl<F> Event for EnqueueIOWithIntegTimes<F>
996    where F: Fn() -> EventBox<()> + Clone + 'static
997{
998    type Item = ();
999
1000    #[doc(hidden)]
1001    #[inline]
1002    fn call_event(self, p: &Point) -> simulation::Result<()> {
1003        let EnqueueIOWithIntegTimes { f } = self;
1004        let comp = EnqueueIOWithIntegTimesLoop { f, iteration: p.iteration };
1005        enqueue_io_event(p.time, comp.into_boxed())
1006            .call_event(p)
1007    }
1008}
1009
1010/// Enqueues the IO-based events with the integration time points in a loop.
1011#[must_use = "computations are lazy and do nothing unless to be run"]
1012#[derive(Clone)]
1013struct EnqueueIOWithIntegTimesLoop<F> {
1014
1015    /// The generator of event handlers.
1016    f: F,
1017
1018    /// The iteration number.
1019    iteration: usize
1020}
1021
1022impl<F> Event for EnqueueIOWithIntegTimesLoop<F>
1023    where F: Fn() -> EventBox<()> + Clone + 'static
1024{
1025    type Item = ();
1026
1027    #[doc(hidden)]
1028    #[inline]
1029    fn call_event(self, p: &Point) -> simulation::Result<()> {
1030        let EnqueueIOWithIntegTimesLoop { f, iteration } = self;
1031        let comp = f();
1032        let p = p.with_iteration(iteration); // correction
1033        comp.call_event(&p)?;
1034        let p2 = p.with_iteration(1 + iteration);
1035        let comp = EnqueueIOWithIntegTimesLoop { f, iteration: p2.iteration };
1036        enqueue_io_event(p2.time, comp.into_boxed())
1037            .call_event(&p)
1038    }
1039}
1040
1041/// The monadic bind for the `Event` computation.
1042#[must_use = "computations are lazy and do nothing unless to be run"]
1043#[derive(Clone)]
1044pub struct AndThen<M, U, F> {
1045
1046    /// The current computation.
1047    comp: M,
1048
1049    /// The continuation of the current computation.
1050    f: F,
1051
1052    /// To keep the type parameter.
1053    _phantom: PhantomData<U>
1054}
1055
1056impl<M, U, F> Event for AndThen<M, U, F>
1057    where M: Event,
1058          U: Event,
1059          F: FnOnce(M::Item) -> U,
1060{
1061    type Item = U::Item;
1062
1063    #[doc(hidden)]
1064    #[inline]
1065    fn call_event(self, p: &Point) -> simulation::Result<U::Item> {
1066        let AndThen { comp, f, _phantom } = self;
1067        match comp.call_event(p) {
1068            Result::Ok(a) => {
1069                let m = f(a);
1070                m.call_event(p)
1071            },
1072            Result::Err(e) => {
1073                Result::Err(e)
1074            }
1075        }
1076    }
1077}
1078
1079/// The functor for the `Event` computation.
1080#[must_use = "computations are lazy and do nothing unless to be run"]
1081#[derive(Clone)]
1082pub struct Map<M, B, F> {
1083
1084    /// The current computation.
1085    comp: M,
1086
1087    /// The transform.
1088    f: F,
1089
1090    /// To keep the type parameter.
1091    _phantom: PhantomData<B>
1092}
1093
1094impl<M, B, F> Event for Map<M, B, F>
1095    where M: Event,
1096          F: FnOnce(M::Item) -> B,
1097{
1098    type Item = B;
1099
1100    #[doc(hidden)]
1101    #[inline]
1102    fn call_event(self, p: &Point) -> simulation::Result<B> {
1103        let Map { comp, f, _phantom } = self;
1104        match comp.call_event(p) {
1105            Result::Ok(a) => Result::Ok(f(a)),
1106            Result::Err(e) => Result::Err(e)
1107        }
1108    }
1109}
1110
1111/// The zip of two `Event` computations.
1112#[must_use = "computations are lazy and do nothing unless to be run"]
1113#[derive(Clone)]
1114pub struct Zip<M, U> {
1115
1116    /// The current computation.
1117    comp: M,
1118
1119    /// Another computation.
1120    other: U,
1121}
1122
1123impl<M, U> Event for Zip<M, U>
1124    where M: Event,
1125          U: Event
1126{
1127    type Item = (M::Item, U::Item);
1128
1129    #[doc(hidden)]
1130    #[inline]
1131    fn call_event(self, p: &Point) -> simulation::Result<(M::Item, U::Item)> {
1132        let Zip { comp, other } = self;
1133        comp.and_then(move |a| {
1134            other.map(move |b| (a, b))
1135        }).call_event(p)
1136    }
1137}
1138
1139/// The function application for the `Event` computation.
1140#[must_use = "computations are lazy and do nothing unless to be run"]
1141#[derive(Clone)]
1142pub struct Ap<M, U, B> {
1143
1144    /// The current computation.
1145    comp: M,
1146
1147    /// The continuation of the current computation.
1148    other: U,
1149
1150    /// To keep the type parameter.
1151    _phantom: PhantomData<B>
1152}
1153
1154impl<M, U, B> Event for Ap<M, U, B>
1155    where M: Event,
1156          U: Event,
1157          M::Item: FnOnce(U::Item) -> B,
1158{
1159    type Item = B;
1160
1161    #[doc(hidden)]
1162    #[inline]
1163    fn call_event(self, p: &Point) -> simulation::Result<B> {
1164        let Ap { comp, other, _phantom } = self;
1165        comp.and_then(move |f| {
1166            other.map(move |a| { f(a) })
1167        }).call_event(p)
1168    }
1169}
1170
1171/// Run the computation in the start time.
1172#[must_use = "computations are lazy and do nothing unless to be run"]
1173#[derive(Clone)]
1174pub struct RunInStartTime<M> {
1175
1176    /// The current computation.
1177    comp: M,
1178
1179    /// Whether to include the current events.
1180    including_current_events: bool
1181}
1182
1183impl<M> Simulation for RunInStartTime<M>
1184    where M: Event
1185{
1186    type Item = M::Item;
1187
1188    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
1189    #[doc(hidden)]
1190    #[inline]
1191    fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
1192        let RunInStartTime { comp, including_current_events } = self;
1193        let p = r.point_in_start_time();
1194        let queue = &r.event_queue;
1195        queue.run_events(including_current_events, &p)?;
1196        comp.call_event(&p)
1197    }
1198
1199    #[cfg(feature="dist_mode")]
1200    #[doc(hidden)]
1201    #[inline]
1202    fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
1203        let RunInStartTime { comp, including_current_events } = self;
1204        let p = r.point_in_start_time();
1205        let including_current_events = if including_current_events { 1 } else { 0 };
1206        unsafe {
1207            sync_extern_events(including_current_events, &p);
1208        }
1209        comp.call_event(&p)
1210    }
1211}
1212
1213/// Run the computation in the stop time.
1214#[must_use = "computations are lazy and do nothing unless to be run"]
1215#[derive(Clone)]
1216pub struct RunInStopTime<M> {
1217
1218    /// The current computation.
1219    comp: M,
1220
1221    /// Whether to include the current events.
1222    including_current_events: bool
1223}
1224
1225impl<M> Simulation for RunInStopTime<M>
1226    where M: Event
1227{
1228    type Item = M::Item;
1229
1230    #[cfg(any(feature="branch_mode", feature="branch_wasm_mode"))]
1231    #[doc(hidden)]
1232    #[inline]
1233    fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
1234        let RunInStopTime { comp, including_current_events } = self;
1235        let p = r.point_in_stop_time();
1236        let queue = &r.event_queue;
1237        queue.run_events(including_current_events, &p)?;
1238        comp.call_event(&p)
1239    }
1240
1241    #[cfg(feature="dist_mode")]
1242    #[doc(hidden)]
1243    #[inline]
1244    fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
1245        let RunInStopTime { comp, including_current_events } = self;
1246        let p = r.point_in_stop_time();
1247        let including_current_events = if including_current_events { 1 } else { 0 };
1248        unsafe {
1249            sync_extern_events(including_current_events, &p);
1250        }
1251        comp.call_event(&p)
1252    }
1253}
1254
1255/// Returns the current simulation time.
1256#[must_use = "computations are lazy and do nothing unless to be run"]
1257#[derive(Clone)]
1258pub struct Time {}
1259
1260impl Event for Time {
1261
1262    type Item = f64;
1263
1264    #[doc(hidden)]
1265    #[inline]
1266    fn call_event(self, p: &Point) -> simulation::Result<f64> {
1267        Result::Ok(p.time)
1268    }
1269}
1270
1271/// Returns the current simulation time priority.
1272#[must_use = "computations are lazy and do nothing unless to be run"]
1273#[derive(Clone)]
1274pub struct Priority {}
1275
1276impl Event for Priority {
1277
1278    type Item = isize;
1279
1280    #[doc(hidden)]
1281    #[inline]
1282    fn call_event(self, p: &Point) -> simulation::Result<isize> {
1283        Result::Ok(p.priority)
1284    }
1285}
1286
1287/// Allows converting to the `Process` computation.
1288#[must_use = "computations are lazy and do nothing unless to be run"]
1289#[derive(Clone)]
1290pub struct EventIntoProcess<M> {
1291
1292    /// The current computation.
1293    comp: M
1294}
1295
1296impl<M> Process for EventIntoProcess<M>
1297    where M: Event
1298{
1299    type Item = M::Item;
1300
1301    #[doc(hidden)]
1302    #[inline]
1303    fn call_process<C>(self, cont: C, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()>
1304        where C: FnOnce(simulation::Result<Self::Item>, Grc<ProcessId>, &Point) -> simulation::Result<()> + Clone + 'static
1305    {
1306        if is_process_cancelled(&pid, p) {
1307            revoke_process(cont, pid, p)
1308        } else {
1309            let EventIntoProcess { comp } = self;
1310            let t = comp.call_event(p);
1311            cont(t, pid, p)
1312        }
1313    }
1314
1315    #[doc(hidden)]
1316    #[inline]
1317    fn call_process_boxed(self, cont: ProcessBoxCont<Self::Item>, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()> {
1318        if is_process_cancelled(&pid, p) {
1319            revoke_process_boxed(cont, pid, p)
1320        } else {
1321            let EventIntoProcess { comp } = self;
1322            let t = comp.call_event(p);
1323            cont.call_box((t, pid, p))
1324        }
1325    }
1326}
1327
1328/// A conversion into the `Composite` computation.
1329#[must_use = "computations are lazy and do nothing unless to be run"]
1330#[derive(Clone)]
1331pub struct EventIntoComposite<M> {
1332
1333    /// The current computation.
1334    comp: M
1335}
1336
1337impl<M> Composite for EventIntoComposite<M>
1338    where M: Event
1339{
1340    type Item = M::Item;
1341
1342    #[doc(hidden)]
1343    #[inline]
1344    fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(M::Item, DisposableBox)> {
1345        let EventIntoComposite { comp } = self;
1346        let a = comp.call_event(p)?;
1347        Result::Ok((a, disposable))
1348    }
1349}
1350
1351/// The sequence of computations.
1352#[must_use = "computations are lazy and do nothing unless to be run"]
1353#[derive(Clone)]
1354pub struct Sequence<I, M> {
1355
1356    /// The computations.
1357    comps: I,
1358
1359    /// To keep the type parameter.
1360    _phantom: PhantomData<M>
1361}
1362
1363impl<I, M> Event for Sequence<I, M>
1364    where I: Iterator<Item = M>,
1365          M: Event
1366{
1367    type Item = Vec<M::Item>;
1368
1369    #[doc(hidden)]
1370    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
1371        let Sequence { comps, _phantom } = self;
1372        let mut v = {
1373            match comps.size_hint() {
1374                (_, Some(n)) => Vec::with_capacity(n),
1375                (_, None) => Vec::new()
1376            }
1377        };
1378        for m in comps {
1379            match m.call_event(p) {
1380                Result::Ok(a) => {
1381                    v.push(a)
1382                },
1383                Result::Err(e) => {
1384                    return Result::Err(e)
1385                }
1386            }
1387        }
1388        Result::Ok(v)
1389    }
1390}
1391
1392/// The sequence of computations with ignored result.
1393#[must_use = "computations are lazy and do nothing unless to be run"]
1394#[derive(Clone)]
1395pub struct Sequence_<I, M> {
1396
1397    /// The computations.
1398    comps: I,
1399
1400    /// To keep the type parameter.
1401    _phantom: PhantomData<M>
1402}
1403
1404impl<I, M> Event for Sequence_<I, M>
1405    where I: Iterator<Item = M>,
1406          M: Event
1407{
1408    type Item = ();
1409
1410    #[doc(hidden)]
1411    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
1412        let Sequence_ { comps, _phantom } = self;
1413        for m in comps {
1414            match m.call_event(p) {
1415                Result::Ok(_) => (),
1416                Result::Err(e) => return Result::Err(e)
1417            }
1418        }
1419        Result::Ok(())
1420    }
1421}
1422
1423/// Enqueue the event which must be actuated with the current modeling time but later.
1424#[must_use = "computations are lazy and do nothing unless to be run"]
1425#[derive(Clone)]
1426pub struct Yield<M> {
1427
1428    /// The computation.
1429    comp: M
1430}
1431
1432impl<M> Event for Yield<M>
1433    where M: Event<Item = ()> + Clone + 'static
1434{
1435    type Item = ();
1436
1437    #[doc(hidden)]
1438    #[inline]
1439    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
1440        let Yield { comp } = self;
1441        enqueue_event(p.time, comp.into_boxed()).call_event(p)
1442    }
1443}
1444
1445/// A computation that tries to leave the simulation.
1446#[cfg(feature="dist_mode")]
1447#[must_use = "computations are lazy and do nothing unless to be run"]
1448#[derive(Clone)]
1449pub struct LeaveSimulation {}
1450
1451#[cfg(feature="dist_mode")]
1452impl Event for LeaveSimulation {
1453
1454    type Item = ();
1455
1456    #[doc(hidden)]
1457    #[inline]
1458    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
1459        let LeaveSimulation {} = self;
1460        let r = p.run;
1461        let q = r.event_queue;
1462        unsafe {
1463            leave_extern_simulation(q, p);
1464        }
1465        Result::Ok(())
1466    }
1467}
1468
1469/// Trace the computation.
1470#[must_use = "computations are lazy and do nothing unless to be run"]
1471#[derive(Clone)]
1472pub struct Trace<M> {
1473
1474    /// The computation.
1475    comp: M,
1476
1477    /// The message to print.
1478    msg: String
1479}
1480
1481impl<M> Event for Trace<M>
1482    where M: Event
1483{
1484    type Item = M::Item;
1485
1486    #[doc(hidden)]
1487    #[inline]
1488    fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
1489        let Trace { comp, msg } = self;
1490        p.trace(&msg);
1491        comp.call_event(p)
1492    }
1493}