Skip to content

Instantly share code, notes, and snippets.

@jkarneges
Created May 28, 2019 02:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkarneges/cb1ee686ef97bb05ebe04b5fc67536f4 to your computer and use it in GitHub Desktop.
Save jkarneges/cb1ee686ef97bb05ebe04b5fc67536f4 to your computer and use it in GitHub Desktop.
use std::time::Duration;
use std::thread;
use std::cell::RefCell;
use std::pin::Pin;
use std::future::Future;
use std::task::{Poll, Context, Waker, RawWaker, RawWakerVTable};
use std::marker::Unpin;
thread_local!(static NOTIFY: RefCell<bool> = RefCell::new(true));
mod task {
use crate::NOTIFY;
pub struct Task();
impl Task {
pub fn notify(&self) {
NOTIFY.with(|n| {
*n.borrow_mut() = true;
})
}
}
pub fn current() -> Task {
Task()
}
}
unsafe fn vt_clone(data: *const ()) -> RawWaker {
RawWaker::new(data, &VTABLE)
}
unsafe fn vt_wake(_data: *const ()) {
task::current().notify();
}
unsafe fn vt_wake_by_ref(_data: *const ()) {
}
unsafe fn vt_drop(_data: *const ()) {
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(
vt_clone,
vt_wake,
vt_wake_by_ref,
vt_drop
);
fn run<F>(mut f: F)
where
F: Future<Output = ()> + Unpin,
{
loop {
if NOTIFY.with(|n| {
if *n.borrow() {
*n.borrow_mut() = false;
let rw = RawWaker::new(&(), &VTABLE);
let w = unsafe { Waker::from_raw(rw) };
let mut cx = Context::from_waker(&w);
let p = Pin::new(&mut f);
match F::poll(p, &mut cx) {
Poll::Ready(_) => return true,
Poll::Pending => (),
}
}
thread::sleep(Duration::from_millis(100));
false
}) { break }
}
}
#[derive(Default)]
struct MyFuture {
count: u32,
}
impl Future for MyFuture {
type Output = u32;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
println!("Count: {}", self.count);
match self.count {
3 => Poll::Ready(self.count),
_ => {
self.count += 1;
cx.waker().clone().wake();
Poll::Pending
},
}
}
}
struct AddOneFuture<T>(T);
impl<T> Future for AddOneFuture<T>
where
T: Future + Unpin,
T::Output: std::ops::Add<u32, Output=u32>,
{
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let p = Pin::new(&mut self.0);
match T::poll(p, cx) {
Poll::Ready(count) => {
println!("Final Count: {}", count + 1);
Poll::Ready(())
},
Poll::Pending => Poll::Pending,
}
}
}
fn main() {
let f = MyFuture::default();
run(AddOneFuture(f));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment