Last active
November 6, 2016 22:37
-
-
Save bwindels/f1972763ca5e3d9926c80c240d3f0b7e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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