dvcompute_dist/simulation/observable/
disposable.rs1use 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::Point;
20use crate::simulation::event::Event;
21
22#[cfg(feature="dist_mode")]
23use crate::simulation::error::*;
24
25#[inline]
27pub fn cons_disposable<F>(f: F) -> Cons<F>
28 where F: FnOnce(&Point) -> simulation::Result<()>
29{
30 Cons { f: f }
31}
32
33#[inline]
35pub fn empty_disposable() -> Empty {
36 Empty {}
37}
38
39#[inline]
41pub fn concat_disposables<I, M>(disposables: I) -> Concat<I::IntoIter, M>
42 where I: IntoIterator<Item = M>,
43 M: Disposable
44{
45 Concat { disposables: disposables.into_iter(), _phantom: PhantomData }
46}
47
48#[inline]
50pub fn trace_disposable<M>(msg: String, comp: M) -> Trace<M>
51 where M: Disposable
52{
53 Trace { comp: comp, msg: msg}
54}
55
56pub trait Disposable {
58
59 #[doc(hidden)]
61 fn dispose(self, p: &Point) -> simulation::Result<()>;
62
63 #[inline]
65 fn into_event(self) -> DisposableEvent<Self>
66 where Self: Sized
67 {
68 DisposableEvent { disposable: self }
69 }
70
71 #[inline]
73 fn merge<U>(self, other: U) -> Merge<Self, U>
74 where Self: Sized,
75 U: Disposable
76 {
77 Merge { disposable: self, other: other }
78 }
79
80 #[inline]
82 fn into_boxed(self) -> DisposableBox
83 where Self: Sized + Clone + 'static
84 {
85 DisposableBox::new(move |p: &Point| { self.dispose(p) })
86 }
87}
88
89pub trait IntoDisposable {
91
92 type Disposable: Disposable;
93
94 fn into_disposable(self) -> Self::Disposable;
96}
97
98impl<M: Disposable> IntoDisposable for M {
99
100 type Disposable = M;
101
102 #[inline]
103 fn into_disposable(self) -> Self::Disposable {
104 self
105 }
106}
107
108pub struct DisposableBox {
110 f: Box<dyn DisposableFnBoxClone>
111}
112
113impl DisposableBox {
114
115 #[doc(hidden)]
117 #[inline]
118 fn new<F>(f: F) -> Self
119 where F: FnOnce(&Point) -> simulation::Result<()> + Clone + 'static
120 {
121 DisposableBox {
122 f: Box::new(f)
123 }
124 }
125
126 #[doc(hidden)]
128 #[inline]
129 pub fn call_box(self, arg: (&Point,)) -> simulation::Result<()> {
130 let DisposableBox { f } = self;
131 f.call_box(arg)
132 }
133}
134
135impl Clone for DisposableBox {
136
137 fn clone(&self) -> Self {
138 DisposableBox {
139 f: self.f.call_clone()
140 }
141 }
142}
143
144impl Disposable for DisposableBox {
145
146 #[doc(hidden)]
147 #[inline]
148 fn dispose(self, p: &Point) -> simulation::Result<()> {
149 self.call_box((p,))
150 }
151
152 #[inline]
153 fn into_boxed(self) -> DisposableBox
154 where Self: Sized + 'static
155 {
156 self
157 }
158}
159
160trait DisposableFnBox {
162
163 fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<()>;
165}
166
167impl<F> DisposableFnBox for F
168 where F: for<'a> FnOnce(&'a Point) -> simulation::Result<()>
169{
170 fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<()> {
171 let this: Self = *self;
172 this(args.0)
173 }
174}
175
176trait DisposableFnBoxClone: DisposableFnBox {
178
179 fn call_clone(&self) -> Box<dyn DisposableFnBoxClone>;
181}
182
183impl<F> DisposableFnBoxClone for F
184 where F: for<'a> FnOnce(&'a Point) -> simulation::Result<()> + Clone + 'static
185{
186 fn call_clone(&self) -> Box<dyn DisposableFnBoxClone> {
187 Box::new(self.clone())
188 }
189}
190
191#[cfg(feature="dist_mode")]
193#[repr(C)]
194#[derive(Copy, Clone)]
195struct DisposableTraitObject {
196
197 field1: *mut c_void,
198 field2: *mut c_void
199}
200
201#[cfg(feature="dist_mode")]
203#[repr(C)]
204pub struct DisposableRepr {
205
206 delete: unsafe extern "C" fn(obj: *mut DisposableTraitObject),
208
209 clone: unsafe extern "C" fn(obj: *const DisposableTraitObject) -> DisposableRepr,
211
212 callback: unsafe extern "C" fn(obj: *mut DisposableTraitObject, p: *const Point) -> *mut ErrorRepr,
214
215 trait_object: DisposableTraitObject
217}
218
219#[cfg(feature="dist_mode")]
220impl Drop for DisposableRepr {
221
222 fn drop(&mut self) {
223 unsafe {
224 (self.delete)(&mut self.trait_object);
225 }
226 }
227}
228
229#[cfg(feature="dist_mode")]
230impl Clone for DisposableRepr {
231
232 fn clone(&self) -> Self {
233 unsafe {
234 (self.clone)(&self.trait_object)
235 }
236 }
237}
238
239#[cfg(feature="dist_mode")]
240impl DisposableRepr {
241
242 #[inline]
244 pub fn into_repr(comp: DisposableBox) -> DisposableRepr {
245 unsafe {
246 DisposableRepr {
247 delete: delete_disposable_repr,
248 clone: clone_disposable_repr,
249 callback: call_disposable_repr,
250 trait_object: mem::transmute(comp)
251 }
252 }
253 }
254
255 #[inline]
257 fn call_repr(mut self, p: &Point) -> *mut ErrorRepr {
258 unsafe {
259 let x = (self.callback)(&mut self.trait_object, p);
260 mem::forget(self);
261 x
262 }
263 }
264}
265
266#[cfg(feature="dist_mode")]
268unsafe extern "C" fn call_disposable_repr(comp: *mut DisposableTraitObject, p: *const Point) -> *mut ErrorRepr {
269 let comp: DisposableBox = mem::transmute(*comp);
270 match comp.call_box((&*p,)) {
271 Result::Ok(()) => ptr::null_mut(),
272 Result::Err(e) => {
273 let e = ErrorRepr::new(e);
274 Box::into_raw(Box::new(e))
275 }
276 }
277}
278
279#[cfg(feature="dist_mode")]
281unsafe extern "C" fn clone_disposable_repr(comp: *const DisposableTraitObject) -> DisposableRepr {
282 let comp: DisposableBox = mem::transmute(*comp);
283 let x = DisposableRepr {
284 delete: delete_disposable_repr,
285 clone: clone_disposable_repr,
286 callback: call_disposable_repr,
287 trait_object: mem::transmute(comp.clone())
288 };
289 mem::forget(comp);
290 x
291}
292
293#[cfg(feature="dist_mode")]
295unsafe extern "C" fn delete_disposable_repr(comp: *mut DisposableTraitObject) {
296 let _: DisposableBox = mem::transmute(*comp);
297}
298
299#[cfg(feature="dist_mode")]
300impl Disposable for DisposableRepr {
301
302 #[doc(hidden)]
303 #[inline]
304 fn dispose(self, p: &Point) -> simulation::Result<()> {
305 unsafe {
306 let e = self.call_repr(p);
307 if e == ptr::null_mut() {
308 Result::Ok(())
309 } else {
310 let e = ffi_error_repr_into_error(e);
311 Result::Err(e)
312 }
313 }
314 }
315}
316
317#[derive(Clone)]
319pub struct Cons<F> {
320
321 f: F
323}
324
325impl<F> Disposable for Cons<F>
326 where F: FnOnce(&Point) -> simulation::Result<()>
327{
328 #[doc(hidden)]
329 #[inline]
330 fn dispose(self, p: &Point) -> simulation::Result<()> {
331 let Cons { f } = self;
332 f(p)
333 }
334}
335
336#[derive(Clone)]
338pub struct Empty {}
339
340impl Disposable for Empty {
341
342 #[doc(hidden)]
343 #[inline]
344 fn dispose(self, _p: &Point) -> simulation::Result<()> {
345 Result::Ok(())
346 }
347}
348
349#[derive(Clone)]
351pub struct Merge<M, U> {
352
353 disposable: M,
355
356 other: U
358}
359
360impl<M, U> Disposable for Merge<M, U>
361 where M: Disposable,
362 U: Disposable
363{
364 #[doc(hidden)]
365 #[inline]
366 fn dispose(self, p: &Point) -> simulation::Result<()> {
367 let Merge { disposable, other } = self;
368 disposable.dispose(p)?;
369 other.dispose(p)
370 }
371}
372
373#[derive(Clone)]
375pub struct DisposableEvent<D> {
376
377 disposable: D
379}
380
381impl<D> Event for DisposableEvent<D>
382 where D: Disposable
383{
384 type Item = ();
385
386 #[doc(hidden)]
387 #[inline]
388 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
389 let DisposableEvent { disposable } = self;
390 disposable.dispose(p)
391 }
392}
393
394#[derive(Clone)]
396pub struct Concat<I, M> {
397
398 disposables: I,
400
401 _phantom: PhantomData<M>
403}
404
405impl<I, M> Disposable for Concat<I, M>
406 where I: Iterator<Item = M>,
407 M: Disposable
408{
409 #[doc(hidden)]
410 #[inline]
411 fn dispose(self, p: &Point) -> simulation::Result<()> {
412 let Concat { disposables, _phantom } = self;
413 for disposable in disposables {
414 disposable.dispose(p)?;
415 }
416 Result::Ok(())
417 }
418}
419
420#[must_use = "computations are lazy and do nothing unless to be run"]
422#[derive(Clone)]
423pub struct Trace<M> {
424
425 comp: M,
427
428 msg: String
430}
431
432impl<M> Disposable for Trace<M>
433 where M: Disposable
434{
435 #[doc(hidden)]
436 #[inline]
437 fn dispose(self, p: &Point) -> simulation::Result<()> {
438 let Trace { comp, msg } = self;
439 p.trace(&msg);
440 comp.dispose(p)
441 }
442}