Last active
February 8, 2017 15:32
-
-
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?
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
// 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