Skip to content

Instantly share code, notes, and snippets.

@bwindels
Last active November 6, 2016 22:37
Show Gist options
  • Save bwindels/f1972763ca5e3d9926c80c240d3f0b7e to your computer and use it in GitHub Desktop.
Save bwindels/f1972763ca5e3d9926c80c240d3f0b7e to your computer and use it in GitHub Desktop.
pub trait WakeupChannel : Drop {
fn wakeup(&self)
}
pub trait WakeupBuilder {
fn create(callback: Fn<()>) -> WakeupChannel
}
mod apple {
struct AppleWakeupBuilder {
queue: ffi::dispatch_queue_t
}
impl WakeupBuilder for AppleWakeupBuilder {
fn create(callback: Fn<()>) -> AppleWakeupChannel {
let add_flag = ffi::_dispatch_source_type_data_add;
let evt_source = unsafe {
ffi::dispatch_source_create(add_flag, 0, 0, self.queue)
};
let wakeup_channel = AppleWakeupChannel {
evt_source: evt_source,
callback: callback
};
let channel_ptr = &wakeup_channel as *const _ as *const c_void;
unsafe {
//need box here to have stable memory address that we can make rust forget about easily
//when being invoked by libdispatch
ffi::dispatch_set_context(wakeup_channel.evt_source, channel_ptr);
ffi::dispatch_source_set_event_handler_f(wakeup_channel.evt_source, &wakeup_event_handler);
ffi::dispatch_resume(wakeup_channel.evt_source);
}
wakeup_channel
}
}
#[no_mangle]
extern "C" unsafe fn wakeup_event_handler(context: *const c_void) {
let wakeup_channel : &AppleWakeupChannel = &*(context as *const AppleWakeupChannel);
wakeup_channel.invoke();
}
struct AppleWakeupChannel {
evt_source: dispatch_source_t
callback: Fn<()>
}
impl AppleWakeupChannel {
fn invoke(&self) {
self.callback();
}
}
impl WakeupChannel for AppleWakeupChannel {
fn wakeup(&self) {
dispatch_source_merge_data(self.source, 1u64);
}
}
impl Drop for AppleWakeupChannel {
fn drop(&mut self) {
unsafe { ffi::dispatch_release(self.evt_source); }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment