Skip to content

Instantly share code, notes, and snippets.

@c0gent
Last active February 8, 2017 15:32
Show Gist options
  • Save c0gent/0e8e43987f829069451f0cd7d0dfae7f to your computer and use it in GitHub Desktop.
Save c0gent/0e8e43987f829069451f0cd7d0dfae7f to your computer and use it in GitHub Desktop.
What from tokio or futures can be used as `SomethingGoesHere` to wake up a Task from a foreign thread ffi callback?
// What sort of object can be passed as `user_data` during callback
// registration which can signal back to a parked futures task to wake up?
//
// Assume that the callback will come from another thread and that
// solutions involving constant repeated calls to `poll` to check
// whether or not the callback has already happened are too wasteful.
//
// This probably has something to do with unpark and unpark events
// associated with tasks but how do those work in a potentially
// multi-threaded scenario. Does tokio-core provide something that can
// be passed through C and across threads to `::wake_up`?
/// Does something to wake up a task on a thread pool or tokio core.
extern "C" fn wake_up(event_status: i32, user_data: *mut c_void) {
if event_status == Complete {
let something_ptr = user_data as *mut _ as *mut SomethingGoesHere;
let something = unsafe { Box::from_raw(something_ptr) };
// Do something with `SomethingGoesHere` to wake up task causing it
// to complete.
}
}
/// A buffer which may or may not be ready to read.
struct FutureBuffer {
buffer: Option<Vec<u8>>,
bool: callback_is_registered,
}
impl Future for FutureBuffer {
type Item = Vec<u8>;
type Error = ();
// [NOTE]: I realize that the idiomatic solution might be to set up
// the callback ahead of time to toggle a boolean within a mutex or
// some such and query it upon each poll. Assume that this would be
// too costly for this application and that a more direct method
// using callbacks is necessary.
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
if !self.callback_is_registered {
c_lib::register_callback(wake_up, SomethingGoesHere);
self.callback_is_registered = true;
task::park();
continue;
} else {
// Check something to make sure it was the callback that
// woke us up.
return Ok(Async::Ready(self.buffer.take()))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment