use std::error::Error as StdError;
use libuv_sys2::{self as ffi, uv_async_t};
use crate::{Error, Handle};
type Callback = Box<dyn FnMut() -> Result<(), Box<dyn StdError>> + 'static>;
#[derive(Clone)]
pub struct AsyncHandle {
handle: Handle<uv_async_t, Callback>,
}
unsafe impl Send for AsyncHandle {}
unsafe impl Sync for AsyncHandle {}
impl AsyncHandle {
pub fn new<E, Cb>(mut callback: Cb) -> Result<Self, Error>
where
E: StdError + 'static,
Cb: FnMut() -> Result<(), E> + 'static,
{
let mut handle = Handle::new(|uv_loop, handle| unsafe {
ffi::uv_async_init(
uv_loop,
handle.as_mut_ptr(),
Some(async_cb as _),
)
})?;
let callback: Callback = Box::new(move || {
callback().map_err(|err| Box::new(err) as Box<dyn StdError>)
});
unsafe { handle.set_data(callback) };
Ok(Self { handle })
}
pub fn send(&self) -> Result<(), Error> {
let retv =
unsafe { ffi::uv_async_send(self.handle.as_ptr() as *mut _) };
if retv < 0 {
return Err(Error::AsyncTrigger);
}
Ok(())
}
}
extern "C" fn async_cb(ptr: *mut uv_async_t) {
let handle: Handle<_, Callback> = unsafe { Handle::from_raw(ptr) };
let callback = unsafe { handle.get_data() };
if !callback.is_null() {
let callback = unsafe { &mut *callback };
if let Err(_err) = callback() {
}
}
}