emf_core_base_rs_ffi/sys/
sync_handler.rs

1//! Interface of a sync handler
2//!
3//! Any object that can be wrapped into a [SyncHandlerInterface] can be used as a sync handler.
4use crate::{Bool, TypeWrapper};
5use std::ptr::NonNull;
6
7/// Opaque structure representing a sync handler.
8#[repr(C)]
9pub struct SyncHandler {
10    _dummy: [u8; 0],
11}
12
13pub type LockFn = TypeWrapper<unsafe extern "C-unwind" fn(handler: Option<NonNull<SyncHandler>>)>;
14pub type TryLockFn =
15    TypeWrapper<unsafe extern "C-unwind" fn(handler: Option<NonNull<SyncHandler>>) -> Bool>;
16pub type UnlockFn = TypeWrapper<unsafe extern "C-unwind" fn(handler: Option<NonNull<SyncHandler>>)>;
17
18/// Interface of a sync handler.
19#[repr(C)]
20#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
21pub struct SyncHandlerInterface {
22    pub handler: Option<NonNull<SyncHandler>>,
23    pub lock_fn: LockFn,
24    pub try_lock_fn: TryLockFn,
25    pub unlock_fn: UnlockFn,
26}
27
28unsafe impl Send for SyncHandlerInterface {}
29unsafe impl Sync for SyncHandlerInterface {}
30
31/// Helper trait for using a sync handler.
32pub trait SyncHandlerBinding {
33    /// Locks the synchronisation handler.
34    ///
35    /// The calling thread is stalled until the lock can be acquired.
36    /// Only one thread can hold the lock at a time.
37    ///
38    /// # Safety
39    ///
40    /// The function crosses the ffi boundary.
41    /// Direct usage of a [SyncHandlerBinding] may break some invariants
42    /// of the sys api, if not handled with care.
43    unsafe fn lock(&self);
44
45    /// Tries to lock the synchronisation handler.
46    ///
47    /// The function fails if another thread already holds the lock.
48    ///
49    /// # Return
50    ///
51    /// [Bool::True] on success and [Bool::False] otherwise.
52    ///
53    /// # Safety
54    ///
55    /// The function crosses the ffi boundary.
56    /// Direct usage of a [SyncHandlerBinding] may break some invariants
57    /// of the sys api, if not handled with care.
58    unsafe fn try_lock(&self) -> Bool;
59
60    /// Unlocks the synchronisation handler.
61    ///
62    /// # Safety
63    ///
64    /// The function crosses the ffi boundary.
65    /// Trying to call this function without prior locking is undefined behaviour.
66    /// Direct usage of a [SyncHandlerBinding] may break some invariants
67    /// of the sys api, if not handled with care.
68    unsafe fn unlock(&self);
69}
70
71impl SyncHandlerBinding for SyncHandlerInterface {
72    #[inline]
73    unsafe fn lock(&self) {
74        (self.lock_fn)(self.handler)
75    }
76
77    #[inline]
78    unsafe fn try_lock(&self) -> Bool {
79        (self.try_lock_fn)(self.handler)
80    }
81
82    #[inline]
83    unsafe fn unlock(&self) {
84        (self.unlock_fn)(self.handler)
85    }
86}