use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock};
use crate::callbacks;
use crate::error::{check, Result};
use crate::generated::{Event, EventHandler};
use crate::marshal;
use crate::object::{BaseObject, Interface};
use crate::sys;
fn handler_slots() -> &'static Mutex<HashMap<usize, usize>> {
static SLOTS: OnceLock<Mutex<HashMap<usize, usize>>> = OnceLock::new();
SLOTS.get_or_init(|| Mutex::new(HashMap::new()))
}
impl EventHandler {
pub fn from_fn(
handler: impl Fn(Option<BaseObject>, Option<BaseObject>) + Send + Sync + 'static,
) -> Result<EventHandler> {
let op = "daqEventHandler_createEventHandler";
let (trampoline, index) = callbacks::allocate_event(Arc::new(handler))?;
let mut out: *mut sys::daqEventHandler = std::ptr::null_mut();
let code = unsafe { (sys::api().daqEventHandler_createEventHandler)(&mut out, trampoline) };
if let Err(e) = check(code, op) {
callbacks::free_event(index);
return Err(e);
}
let handler = unsafe { marshal::require_object::<EventHandler>(out as *mut _, op) }
.inspect_err(|_| callbacks::free_event(index))?;
handler_slots()
.lock()
.unwrap()
.insert(handler.as_raw() as usize, index);
Ok(handler)
}
}
impl Event {
pub fn subscribe(
&self,
handler: impl Fn(Option<BaseObject>, Option<BaseObject>) + Send + Sync + 'static,
) -> Result<EventHandler> {
let handler = EventHandler::from_fn(handler)?;
self.add_handler(&handler)?;
Ok(handler)
}
pub fn unsubscribe(&self, handler: &EventHandler) -> Result<()> {
self.remove_handler(handler)?;
if let Some(index) = handler_slots()
.lock()
.unwrap()
.remove(&(handler.as_raw() as usize))
{
callbacks::free_event(index);
}
Ok(())
}
}