emf_core_base_rs_ffi/sys/
api.rs

1//! Sys api.
2//!
3//! The sys api is exposed by the [SysBinding] trait.
4use crate::collections::{NonNullConst, Optional};
5use crate::sys::sync_handler::SyncHandlerInterface;
6use crate::{Bool, CBase, CBaseFn, CBaseInterface, FnId, TypeWrapper};
7use std::ptr::NonNull;
8
9pub type ShutdownFn =
10    TypeWrapper<unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>) -> !>;
11
12pub type PanicFn = TypeWrapper<
13    unsafe extern "C-unwind" fn(
14        base_module: Option<NonNull<CBase>>,
15        error: Option<NonNullConst<u8>>,
16    ) -> !,
17>;
18
19pub type HasFunctionFn =
20    TypeWrapper<unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>, id: FnId) -> Bool>;
21
22pub type GetFunctionFn = TypeWrapper<
23    unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>, id: FnId) -> Optional<CBaseFn>,
24>;
25
26pub type LockFn = TypeWrapper<unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>)>;
27
28pub type TryLockFn =
29    TypeWrapper<unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>) -> Bool>;
30
31pub type UnlockFn = TypeWrapper<unsafe extern "C-unwind" fn(base_module: Option<NonNull<CBase>>)>;
32
33pub type GetSyncHandlerFn = TypeWrapper<
34    unsafe extern "C-unwind" fn(
35        base_module: Option<NonNull<CBase>>,
36    ) -> NonNullConst<SyncHandlerInterface>,
37>;
38
39pub type SetSyncHandlerFn = TypeWrapper<
40    unsafe extern "C-unwind" fn(
41        base_module: Option<NonNull<CBase>>,
42        handler: Option<NonNullConst<SyncHandlerInterface>>,
43    ),
44>;
45
46/// Helper trait for using the sys api.
47pub trait SysBinding {
48    /// Sends a termination signal.
49    ///
50    /// # Safety
51    ///
52    /// The function is not thread-safe and crosses the ffi boundary.
53    unsafe fn shutdown(&mut self) -> !;
54
55    /// Execution of the program is stopped abruptly. The error may be logged.
56    ///
57    /// # Safety
58    ///
59    /// The function crosses the ffi boundary.
60    unsafe fn panic(&self, error: Option<NonNullConst<u8>>) -> !;
61
62    /// Checks if a function is implemented.
63    ///
64    /// # Return
65    ///
66    /// [Bool::True] if the function exists, [Bool::False] otherwise.
67    ///
68    /// # Safety
69    ///
70    /// The function crosses the ffi boundary.
71    unsafe fn has_function(&self, id: FnId) -> Bool;
72
73    /// Fetches a function from the interface.
74    ///
75    /// # Return
76    ///
77    /// Function pointer to the requested function, if it exists.
78    ///
79    /// # Safety
80    ///
81    /// The function crosses the ffi boundary.
82    unsafe fn get_function(&self, id: FnId) -> Optional<CBaseFn>;
83
84    /// Locks the interface.
85    ///
86    /// The calling thread is stalled until the lock can be acquired.
87    /// Only one thread can hold the lock at a time.
88    ///
89    /// # Safety
90    ///
91    /// The function crosses the ffi boundary.
92    unsafe fn lock(&self);
93
94    /// Tries to lock the interface.
95    ///
96    /// The function fails if another thread already holds the lock.
97    ///
98    /// # Return
99    ///
100    /// [Bool::True] on success and [Bool::False] otherwise.
101    ///
102    /// # Safety
103    ///
104    /// The function crosses the ffi boundary.
105    unsafe fn try_lock(&self) -> Bool;
106
107    /// Unlocks the interface.
108    ///
109    /// # Safety
110    ///
111    /// The function crosses the ffi boundary.
112    /// Trying to call this function without prior locking is undefined behaviour.
113    unsafe fn unlock(&self);
114
115    /// Fetches the active synchronization handler.
116    ///
117    /// # Return
118    ///
119    /// Pointer to the active synchronization handler.
120    ///
121    /// # Safety
122    ///
123    /// The function is not thread-safe and crosses the ffi boundary.
124    unsafe fn get_sync_handler(&self) -> NonNullConst<SyncHandlerInterface>;
125
126    /// Sets a new synchronization handler.
127    ///
128    /// The default synchronization handler is used, if `handler` is [Option::None].
129    ///
130    /// # Uses
131    ///
132    /// This function can be used by modules, that want to provide a more complex
133    /// synchronization mechanism than the one presented by the default handler.
134    ///
135    /// # Swapping
136    ///
137    /// The swapping occurs in three steps:
138    ///
139    /// 1. The new synchronization handler is locked.
140    /// 2. The new synchronization handler is set as the active synchronization handler.
141    /// 3. The old synchronization handler is unlocked.
142    ///
143    /// # Note
144    ///
145    /// Changing the synchronization handler may break some modules,
146    /// if they depend on a specific synchronization handler.
147    ///
148    /// # Safety
149    ///
150    /// The function is not thread-safe and crosses the ffi boundary.
151    unsafe fn set_sync_handler(&mut self, handler: Option<NonNullConst<SyncHandlerInterface>>);
152}
153
154impl SysBinding for CBaseInterface {
155    #[inline]
156    unsafe fn shutdown(&mut self) -> ! {
157        (self.sys_shutdown_fn)(self.base_module)
158    }
159
160    #[inline]
161    unsafe fn panic(&self, error: Option<NonNullConst<u8>>) -> ! {
162        (self.sys_panic_fn)(self.base_module, error)
163    }
164
165    #[inline]
166    unsafe fn has_function(&self, id: FnId) -> Bool {
167        (self.sys_has_function_fn)(self.base_module, id)
168    }
169
170    #[inline]
171    unsafe fn get_function(&self, id: FnId) -> Optional<CBaseFn> {
172        (self.sys_get_function_fn)(self.base_module, id)
173    }
174
175    #[inline]
176    unsafe fn lock(&self) {
177        (self.sys_lock_fn)(self.base_module)
178    }
179
180    #[inline]
181    unsafe fn try_lock(&self) -> Bool {
182        (self.sys_try_lock_fn)(self.base_module)
183    }
184
185    #[inline]
186    unsafe fn unlock(&self) {
187        (self.sys_unlock_fn)(self.base_module)
188    }
189
190    #[inline]
191    unsafe fn get_sync_handler(&self) -> NonNullConst<SyncHandlerInterface> {
192        (self.sys_get_sync_handler_fn)(self.base_module)
193    }
194
195    #[inline]
196    unsafe fn set_sync_handler(&mut self, handler: Option<NonNullConst<SyncHandlerInterface>>) {
197        (self.sys_set_sync_handler_fn)(self.base_module, handler)
198    }
199}