summaryrefslogtreecommitdiffstats
path: root/third_party/rust/coremidi/src/callback.rs
blob: c15ca0da306b3e1ba233eeadf483fbbc29653b96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// A lifetime-managed wrapper for callback functions
#[derive(Debug, PartialEq)]
pub struct BoxedCallback<T>(*mut Box<dyn FnMut(&T)>);

impl<T> BoxedCallback<T> {
    pub fn new<F: FnMut(&T) + Send + 'static>(f: F) -> BoxedCallback<T> {
        BoxedCallback(Box::into_raw(Box::new(Box::new(f))))
    }

    pub fn null() -> BoxedCallback<T> {
        BoxedCallback(::std::ptr::null_mut())
    }

    pub fn raw_ptr(&mut self) -> *mut ::std::os::raw::c_void {
        self.0 as *mut ::std::os::raw::c_void
    }

    // must not be null
    pub unsafe fn call_from_raw_ptr(raw_ptr: *mut ::std::os::raw::c_void, arg: &T) {
        let callback = &mut *(raw_ptr as *mut Box<dyn FnMut(&T)>);
        callback(arg);
    }
}

unsafe impl<T> Send for BoxedCallback<T> {}

impl<T> Drop for BoxedCallback<T> {
    fn drop(&mut self) {
        if !self.0.is_null() {
            unsafe {
                let _ = Box::from_raw(self.0);
            }
        }
    }
}