dvcompute_dist/simulation/internal/
undoable_log.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::mem;
8
9use libc::*;
10
11use crate::simulation::Run;
12
13/// Represents an undoable action.
14pub struct UndoableActionBox {
15    f: Box<dyn UndoableActionFnBox>
16}
17
18impl UndoableActionBox {
19
20    /// Create a new boxed computation.
21    #[doc(hidden)]
22    #[inline]
23    pub fn new<F>(f: F) -> Self
24        where F: FnOnce(&Run) + 'static
25    {
26        UndoableActionBox {
27            f: Box::new(f)
28        }
29    }
30
31    /// Call the boxed function.
32    #[doc(hidden)]
33    #[inline]
34    pub fn call_box(self, arg: (&Run,)) {
35        let UndoableActionBox { f } = self;
36        f.call_box(arg)
37    }
38}
39
40/// A trait to support the stable version of Rust, where there is no `FnBox`.
41trait UndoableActionFnBox {
42
43    /// Call the corresponding function.
44    fn call_box(self: Box<Self>, args: (&Run,));
45}
46
47impl<F> UndoableActionFnBox for F
48    where F: for<'a> FnOnce(&'a Run)
49{
50    fn call_box(self: Box<Self>, args: (&Run,)) {
51        let this: Self = *self;
52        this(args.0)
53    }
54}
55
56/// It represents a raw trait object.
57#[repr(C)]
58#[derive(Copy, Clone)]
59struct UndoableActionTraitObject {
60
61    field1: *mut c_void,
62    field2: *mut c_void
63}
64
65/// A C-friendly representaton of the `UndoableActionBox` action.
66#[repr(C)]
67pub struct UndoableActionRepr {
68
69    /// Delete the object.
70    delete: unsafe extern "C" fn(obj: *mut UndoableActionTraitObject),
71
72    /// The callback.
73    callback: unsafe extern "C" fn(obj: *mut UndoableActionTraitObject, r: *const Run),
74
75    /// The trait object.
76    trait_object: UndoableActionTraitObject
77}
78
79impl Drop for UndoableActionRepr {
80
81    fn drop(&mut self) {
82        unsafe {
83            (self.delete)(&mut self.trait_object);
84        }
85    }
86}
87
88impl UndoableActionRepr {
89
90    /// Convert to a C-friendly representation.
91    #[inline]
92    pub fn into_repr(comp: UndoableActionBox) -> UndoableActionRepr {
93        unsafe {
94            UndoableActionRepr {
95                delete: delete_undoable_action_repr,
96                callback: call_undoable_action_repr,
97                trait_object: mem::transmute(comp)
98            }
99        }
100    }
101
102    /// Call the representation.
103    #[inline]
104    fn _call_repr(mut self, r: &Run) {
105        unsafe {
106            (self.callback)(&mut self.trait_object, r);
107            mem::forget(self);
108        }
109    }
110}
111
112/// Call the `UndoableActionBox` representation.
113unsafe extern "C" fn call_undoable_action_repr(comp: *mut UndoableActionTraitObject, r: *const Run) {
114    let comp: UndoableActionBox = mem::transmute(*comp);
115    comp.call_box((&*r,));
116}
117
118/// Delete the `UndoableActionBox` representation.
119unsafe extern "C" fn delete_undoable_action_repr(comp: *mut UndoableActionTraitObject) {
120    let _: UndoableActionBox = mem::transmute(*comp);
121}
122
123/// Represents a log of undoable actions.
124pub type UndoableLog = c_void;
125
126#[cfg(all(feature="dist_mode", not(feature="dist_core_mode")))]
127#[cfg_attr(windows, link(name = "dvcompute_core_dist.dll"))]
128#[cfg_attr(not(windows), link(name = "dvcompute_core_dist"))]
129extern {
130
131    /// Create a new undoable log.
132    #[doc(hidden)]
133    pub fn create_extern_undoable_log() -> *mut UndoableLog;
134
135    /// Delete the undoable log.
136    #[doc(hidden)]
137    pub fn delete_extern_undoable_log(log: *mut UndoableLog);
138
139    /// Write the new action at the specified modeling time.
140    #[doc(hidden)]
141    pub fn extern_write_log(log: *mut UndoableLog, t: f64, action: UndoableActionRepr);
142}
143
144#[cfg(all(feature="dist_mode", feature="dist_core_mode"))]
145extern {
146
147    /// Create a new undoable log.
148    #[doc(hidden)]
149    pub fn create_extern_undoable_log() -> *mut UndoableLog;
150
151    /// Delete the undoable log.
152    #[doc(hidden)]
153    pub fn delete_extern_undoable_log(log: *mut UndoableLog);
154
155    /// Write the new action at the specified modeling time.
156    #[doc(hidden)]
157    pub fn extern_write_log(log: *mut UndoableLog, t: f64, action: UndoableActionRepr);
158}