Skip to content

Instantly share code, notes, and snippets.

@sdbondi
Last active January 14, 2019 05:51
Show Gist options
  • Save sdbondi/67d5dd36e3a3bc8fd44fb1e0e03c2861 to your computer and use it in GitHub Desktop.
Save sdbondi/67d5dd36e3a3bc8fd44fb1e0e03c2861 to your computer and use it in GitHub Desktop.
First attempt at a future with a call back which runs in it's own thread (Does not compile)
use futures::{Future, Poll, task, Async};
use std::sync::Arc;
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::error::Error;
use std::thread;
use std::marker::{Send, Sync};
use std::sync::Mutex;
///
/// ```
///let future = AsyncJobFuture::new(move || {
/// // do work
/// });
/// return future;
///```
type AsyncJobCallback<T, E> = Arc<FnOnce() -> Result<T, E> + Send + Sync + 'static>;
pub(super) struct AsyncJobFuture<T, E>
where T: Send, E: Send
{
callback: AsyncJobCallback<T, E>,
running: bool,
rx: Receiver<Result<T, E>>,
tx: Sender<Result<T, E>>,
}
impl<T, E> Future for AsyncJobFuture<T, E>
where T: Send + 'static, E: Send + 'static
{
type Item = T;
type Error = E;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.running {
let result = self.rx.try_recv().ok();
match result {
Some(r) => match r {
Ok(inner_result) => Ok(Async::Ready(inner_result)),
Err(err) => Err(err),
}
None => Ok(Async::NotReady),
}
} else {
self.execute_task(task::current());
self.running = true;
Ok(Async::NotReady)
}
}
}
impl<T, E> AsyncJobFuture<T, E>
where T: Send + 'static, E: Send + 'static
{
pub fn new(callback: AsyncJobCallback<T, E>) -> Self {
let (tx, rx): (Sender<Result<T, E>>, Receiver<Result<T, E>>) = mpsc::channel();
Self {
callback,
running: false,
rx,
tx,
}
}
fn execute_task(&self, task: task::Task) {
let mut callback = self.callback.clone();
let tx = self.tx.clone();
thread::spawn(move || {
let result = callback();
tx.send(result).unwrap();
task.notify();
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment