dvcompute/simulation/internal/
event_queue.rs1#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
8use std::cell::UnsafeCell;
9
10#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
11use std::ops::Deref;
12
13#[cfg(feature="cons_mode")]
14use libc::*;
15
16use crate::simulation::error::*;
17use crate::simulation::specs::SpecsRepr;
18use crate::simulation::point::Point;
19use crate::simulation::event::*;
20
21#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
22use crate::simulation;
23
24#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
25use crate::simulation::utils::priority_queue::PriorityQueue;
26
27#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
29pub struct EventQueue {
30
31 time: UnsafeCell<f64>,
33
34 pq: UnsafeCell<PriorityQueue<(f64, isize), EventRepr>>
36}
37
38#[cfg(any(feature="seq_mode", feature="wasm_mode"))]
39impl EventQueue {
40
41 pub fn new(specs: &SpecsRepr) -> EventQueue {
43 EventQueue {
44 time: UnsafeCell::new(specs.start_time),
45 pq: UnsafeCell::new(PriorityQueue::new())
46 }
47 }
48
49 #[inline]
51 pub fn enqueue_event(&self, event_time: f64, priority: isize, comp: EventRepr, p: &Point) {
52 assert!(event_time >= p.time, "The event time cannot be less than the current modeling time");
53 let pq = self.pq.get();
54 unsafe {
55 (*pq).enqueue((event_time, - priority), comp);
56 }
57 }
58
59 #[inline]
61 pub fn enqueue_io_event(&self, event_time: f64, priority: isize, comp: EventRepr, p: &Point) {
62 self.enqueue_event(event_time, priority, comp, p)
63 }
64
65 pub fn run_events(&self, including_current: bool, p: &Point) -> simulation::Result<()> {
67 loop {
68 let ((t2, pri2), c2) = unsafe {
69 let pq = self.pq.get();
70 let t0 = self.time.get();
71 match (*pq).minimal_key() {
72 Some((t2, _)) if *t2 < *t0 => {
73 panic!("The time value is too small. The event queue is desynchronized");
74 }
75 Some((t2, _)) if *t2 < p.time || (including_current && *t2 == p.time) => {
76 *t0 = *t2;
77 }
78 _ => {
79 break;
80 }
81 }
82 (*pq).dequeue()
83 };
84 let run = p.run;
85 let specs = &run.specs;
86 let t0 = specs.start_time;
87 let dt = specs.dt;
88 let n2 = ((t2 - t0) / dt).floor() as usize;
89 let p2 = Point {
90 run: p.run,
91 time: t2,
92 priority: -pri2,
93 minimal_priority: p.minimal_priority,
94 iteration: n2,
95 phase: -1
96 };
97 match c2.call_event(&p2) {
98 Result::Ok(()) => (),
99 Result::Err(Error::Cancel) => (),
100 Result::Err(Error::Other(x)) => {
101 match x.deref() {
102 &OtherError::Retry(_) => {
103 return Result::Err(Error::Other(x.clone()))
104 },
105 &OtherError::Panic(_) => {
106 return Result::Err(Error::Other(x.clone()))
107 },
108 &OtherError::IO(_) => {
109 return Result::Err(Error::Other(x.clone()))
110 }
111 }
112 }
113 }
114 }
115 Result::Ok(())
116 }
117}
118
119#[cfg(feature="cons_mode")]
121pub type EventQueue = c_void;
122
123#[cfg(all(feature="cons_mode", not(feature="cons_core_mode")))]
124#[cfg_attr(windows, link(name = "dvcompute_core_cons.dll"))]
125#[cfg_attr(not(windows), link(name = "dvcompute_core_cons"))]
126extern {
127
128 #[doc(hidden)]
130 pub fn create_extern_event_queue(specs: *const SpecsRepr) -> *mut EventQueue;
131
132 #[doc(hidden)]
134 pub fn delete_extern_event_queue(queue: *mut EventQueue);
135
136 #[doc(hidden)]
138 pub fn enqueue_extern_event(queue: *mut EventQueue, event_time: f64, priority: isize, comp: EventRepr, p: *const Point);
139
140 #[doc(hidden)]
142 pub fn enqueue_extern_io_event(queue: *mut EventQueue, event_time: f64, priority: isize, comp: EventRepr, p: *const Point);
143
144 #[doc(hidden)]
146 pub fn run_extern_events(including_current: isize, p: *const Point) -> *mut ErrorRepr;
147}
148
149#[cfg(all(feature="cons_mode", feature="cons_core_mode"))]
150extern {
151
152 #[doc(hidden)]
154 pub fn create_extern_event_queue(specs: *const SpecsRepr) -> *mut EventQueue;
155
156 #[doc(hidden)]
158 pub fn delete_extern_event_queue(queue: *mut EventQueue);
159
160 #[doc(hidden)]
162 pub fn enqueue_extern_event(queue: *mut EventQueue, event_time: f64, priority: isize, comp: EventRepr, p: *const Point);
163
164 #[doc(hidden)]
166 pub fn enqueue_extern_io_event(queue: *mut EventQueue, event_time: f64, priority: isize, comp: EventRepr, p: *const Point);
167
168 #[doc(hidden)]
170 pub fn run_extern_events(including_current: isize, p: *const Point) -> *mut ErrorRepr;
171}