-
-
Save jkarneges/cb1ee686ef97bb05ebe04b5fc67536f4 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
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