libasync: wrap_waker()

This commit is contained in:
Astro 2020-03-31 18:55:03 +02:00
parent 25e80f63f9
commit 8bc721826c
1 changed files with 8 additions and 9 deletions

View File

@ -30,6 +30,12 @@ static VTABLE: RawWakerVTable = {
RawWakerVTable::new(clone, wake, wake_by_ref, drop) RawWakerVTable::new(clone, wake, wake_by_ref, drop)
}; };
/// ready should not move as long as this waker references it. That is
/// the reason for keeping Tasks in a pinned box.
fn wrap_waker(ready: &AtomicBool) -> Waker {
unsafe { Waker::from_raw(RawWaker::new(ready as *const _ as *const _, &VTABLE)) }
}
/// A single-threaded executor /// A single-threaded executor
/// ///
/// This is a singleton /// This is a singleton
@ -67,8 +73,7 @@ impl Executor {
pin_mut!(f); pin_mut!(f);
let ready = AtomicBool::new(true); let ready = AtomicBool::new(true);
let waker = let waker = wrap_waker(&ready);
unsafe { Waker::from_raw(RawWaker::new(&ready as *const _ as *const _, &VTABLE)) };
let val = loop { let val = loop {
// advance the main task // advance the main task
if ready.load(Ordering::Relaxed) { if ready.load(Ordering::Relaxed) {
@ -94,14 +99,8 @@ impl Executor {
// we are about to service the task so switch the `ready` flag to `false` // we are about to service the task so switch the `ready` flag to `false`
task.ready.store(false, Ordering::Relaxed); task.ready.store(false, Ordering::Relaxed);
// NOTE we never deallocate tasks so `&ready` is always pointing to let waker = wrap_waker(&task.ready);
// allocated memory (`&'static AtomicBool`)
let waker = unsafe {
Waker::from_raw(RawWaker::new(&task.ready as *const _ as *const _, &VTABLE))
};
let mut cx = Context::from_waker(&waker); let mut cx = Context::from_waker(&waker);
// this points into a `static` memory so it's already pinned
// println!("run task");
let ready = task.f.as_mut().poll(&mut cx).is_ready(); let ready = task.f.as_mut().poll(&mut cx).is_ready();
if ready { if ready {
// Task is finished, do not requeue // Task is finished, do not requeue