dvcompute_cons/simulation/observable/
disposable.rs1use std::marker::PhantomData;
8
9#[cfg(feature="cons_mode")]
10use std::mem;
11
12#[cfg(feature="cons_mode")]
13use std::ptr;
14
15#[cfg(feature="cons_mode")]
16use libc::*;
17
18use crate::simulation;
19use crate::simulation::point::Point;
20use crate::simulation::event::Event;
21
22#[cfg(feature="cons_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 + '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 DisposableFnBox>
111}
112
113impl DisposableBox {
114
115 #[doc(hidden)]
117 #[inline]
118 fn new<F>(f: F) -> Self
119 where F: FnOnce(&Point) -> simulation::Result<()> + '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 Disposable for DisposableBox {
136
137 #[doc(hidden)]
138 #[inline]
139 fn dispose(self, p: &Point) -> simulation::Result<()> {
140 self.call_box((p,))
141 }
142
143 #[inline]
144 fn into_boxed(self) -> DisposableBox
145 where Self: Sized + 'static
146 {
147 self
148 }
149}
150
151trait DisposableFnBox {
153
154 fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<()>;
156}
157
158impl<F> DisposableFnBox for F
159 where F: for<'a> FnOnce(&'a Point) -> simulation::Result<()>
160{
161 fn call_box(self: Box<Self>, args: (&Point,)) -> simulation::Result<()> {
162 let this: Self = *self;
163 this(args.0)
164 }
165}
166
167#[cfg(feature="cons_mode")]
169#[repr(C)]
170#[derive(Copy, Clone)]
171struct DisposableTraitObject {
172
173 field1: *mut c_void,
174 field2: *mut c_void
175}
176
177#[cfg(feature="cons_mode")]
179#[repr(C)]
180pub struct DisposableRepr {
181
182 delete: unsafe extern "C" fn(obj: *mut DisposableTraitObject),
184
185 callback: unsafe extern "C" fn(obj: *mut DisposableTraitObject, p: *const Point) -> *mut ErrorRepr,
187
188 trait_object: DisposableTraitObject
190}
191
192#[cfg(feature="cons_mode")]
193impl Drop for DisposableRepr {
194
195 fn drop(&mut self) {
196 unsafe {
197 (self.delete)(&mut self.trait_object);
198 }
199 }
200}
201
202#[cfg(feature="cons_mode")]
203impl DisposableRepr {
204
205 #[inline]
207 pub fn into_repr(comp: DisposableBox) -> DisposableRepr {
208 unsafe {
209 DisposableRepr {
210 delete: delete_disposable_repr,
211 callback: call_disposable_repr,
212 trait_object: mem::transmute(comp)
213 }
214 }
215 }
216
217 #[inline]
219 fn call_repr(mut self, p: &Point) -> *mut ErrorRepr {
220 unsafe {
221 let x = (self.callback)(&mut self.trait_object, p);
222 mem::forget(self);
223 x
224 }
225 }
226}
227
228#[cfg(feature="cons_mode")]
230unsafe extern "C" fn call_disposable_repr(comp: *mut DisposableTraitObject, p: *const Point) -> *mut ErrorRepr {
231 let comp: DisposableBox = mem::transmute(*comp);
232 match comp.call_box((&*p,)) {
233 Result::Ok(()) => ptr::null_mut(),
234 Result::Err(e) => {
235 let e = ErrorRepr::new(e);
236 Box::into_raw(Box::new(e))
237 }
238 }
239}
240
241#[cfg(feature="cons_mode")]
243unsafe extern "C" fn delete_disposable_repr(comp: *mut DisposableTraitObject) {
244 let _: DisposableBox = mem::transmute(*comp);
245}
246
247#[cfg(feature="cons_mode")]
248impl Disposable for DisposableRepr {
249
250 #[doc(hidden)]
251 #[inline]
252 fn dispose(self, p: &Point) -> simulation::Result<()> {
253 unsafe {
254 let e = self.call_repr(p);
255 if e == ptr::null_mut() {
256 Result::Ok(())
257 } else {
258 let e = ffi_error_repr_into_error(e);
259 Result::Err(e)
260 }
261 }
262 }
263}
264
265#[derive(Clone)]
267pub struct Cons<F> {
268
269 f: F
271}
272
273impl<F> Disposable for Cons<F>
274 where F: FnOnce(&Point) -> simulation::Result<()>
275{
276 #[doc(hidden)]
277 #[inline]
278 fn dispose(self, p: &Point) -> simulation::Result<()> {
279 let Cons { f } = self;
280 f(p)
281 }
282}
283
284#[derive(Clone)]
286pub struct Empty {}
287
288impl Disposable for Empty {
289
290 #[doc(hidden)]
291 #[inline]
292 fn dispose(self, _p: &Point) -> simulation::Result<()> {
293 Result::Ok(())
294 }
295}
296
297#[derive(Clone)]
299pub struct Merge<M, U> {
300
301 disposable: M,
303
304 other: U
306}
307
308impl<M, U> Disposable for Merge<M, U>
309 where M: Disposable,
310 U: Disposable
311{
312 #[doc(hidden)]
313 #[inline]
314 fn dispose(self, p: &Point) -> simulation::Result<()> {
315 let Merge { disposable, other } = self;
316 disposable.dispose(p)?;
317 other.dispose(p)
318 }
319}
320
321#[derive(Clone)]
323pub struct DisposableEvent<D> {
324
325 disposable: D
327}
328
329impl<D> Event for DisposableEvent<D>
330 where D: Disposable
331{
332 type Item = ();
333
334 #[doc(hidden)]
335 #[inline]
336 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
337 let DisposableEvent { disposable } = self;
338 disposable.dispose(p)
339 }
340}
341
342#[derive(Clone)]
344pub struct Concat<I, M> {
345
346 disposables: I,
348
349 _phantom: PhantomData<M>
351}
352
353impl<I, M> Disposable for Concat<I, M>
354 where I: Iterator<Item = M>,
355 M: Disposable
356{
357 #[doc(hidden)]
358 #[inline]
359 fn dispose(self, p: &Point) -> simulation::Result<()> {
360 let Concat { disposables, _phantom } = self;
361 for disposable in disposables {
362 disposable.dispose(p)?;
363 }
364 Result::Ok(())
365 }
366}
367
368#[must_use = "computations are lazy and do nothing unless to be run"]
370#[derive(Clone)]
371pub struct Trace<M> {
372
373 comp: M,
375
376 msg: String
378}
379
380impl<M> Disposable for Trace<M>
381 where M: Disposable
382{
383 #[doc(hidden)]
384 #[inline]
385 fn dispose(self, p: &Point) -> simulation::Result<()> {
386 let Trace { comp, msg } = self;
387 p.trace(&msg);
388 comp.dispose(p)
389 }
390}