WIP: skeleton of rt::future using a global semaphore
This commit is contained in:
parent
74f76b300e
commit
d648fc94d9
|
@ -35,6 +35,10 @@ panic = "abort"
|
|||
lto = "on"
|
||||
debug = true
|
||||
|
||||
[[example]]
|
||||
name = "async"
|
||||
path = "rust/examples/async.rs"
|
||||
|
||||
[[example]]
|
||||
name = "donate"
|
||||
path = "rust/examples/donate.rs"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#![no_main]
|
||||
|
||||
rt::semaphore!(SEM, 0);
|
||||
|
||||
async fn foo() -> i32 {
|
||||
SEM.async_wait().await;
|
||||
1
|
||||
}
|
||||
|
||||
fn poster() {
|
||||
rt::task::sleep(10);
|
||||
SEM.post();
|
||||
}
|
||||
|
||||
fn async_runner() {
|
||||
assert_eq!(rt::future::block_on(foo()), 1);
|
||||
rt::trap()
|
||||
}
|
||||
|
||||
rt::task!(poster, rt::task::STACK_MIN, 2);
|
||||
|
||||
/* TODO: block_on with a semaphore async_wait doesn't actually block (right now), so this task must
|
||||
* be lower priority to allow poster to run. */
|
||||
rt::task!(async_runner, rt::task::STACK_MIN, 1);
|
|
@ -0,0 +1,43 @@
|
|||
use core::{
|
||||
future::Future,
|
||||
pin::pin,
|
||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
||||
};
|
||||
|
||||
use crate::{semaphore_binary, sync::Semaphore};
|
||||
|
||||
static SEM_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
|
||||
|
||||
semaphore_binary!(SEM_WAKER);
|
||||
|
||||
unsafe fn clone(w: *const ()) -> RawWaker {
|
||||
RawWaker::new(w, &SEM_WAKER_VTABLE)
|
||||
}
|
||||
|
||||
unsafe fn wake(w: *const ()) {
|
||||
wake_by_ref(w)
|
||||
}
|
||||
|
||||
unsafe fn wake_by_ref(w: *const ()) {
|
||||
let sem = &*(w as *mut () as *mut Semaphore);
|
||||
sem.post();
|
||||
}
|
||||
|
||||
unsafe fn drop(_: *const ()) {}
|
||||
|
||||
pub fn block_on<F: Future>(f: F) -> F::Output {
|
||||
let waker = unsafe {
|
||||
Waker::from_raw(RawWaker::new(
|
||||
&SEM_WAKER as *const Semaphore as *const (),
|
||||
&SEM_WAKER_VTABLE,
|
||||
))
|
||||
};
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
let mut f = pin!(f);
|
||||
loop {
|
||||
if let Poll::Ready(o) = f.as_mut().poll(&mut cx) {
|
||||
return o;
|
||||
}
|
||||
SEM_WAKER.wait();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
pub mod cycle;
|
||||
pub mod future;
|
||||
pub mod sync;
|
||||
pub mod task;
|
||||
pub mod tick;
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use core::{
|
||||
cell::UnsafeCell,
|
||||
ffi::c_int,
|
||||
future::Future,
|
||||
marker::PhantomPinned,
|
||||
mem::{size_of, transmute},
|
||||
panic::{RefUnwindSafe, UnwindSafe},
|
||||
pin::Pin,
|
||||
ptr::null_mut,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -90,6 +93,10 @@ impl Semaphore {
|
|||
self.acquire();
|
||||
SemaphoreGuard { sem: self }
|
||||
}
|
||||
|
||||
pub fn async_wait(&self) -> WaitFuture {
|
||||
WaitFuture { sem: self }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SemaphoreGuard<'a> {
|
||||
|
@ -102,6 +109,24 @@ impl<'a> Drop for SemaphoreGuard<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct WaitFuture<'a> {
|
||||
sem: &'a Semaphore,
|
||||
}
|
||||
|
||||
impl Future for WaitFuture<'_> {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.sem.try_wait() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
// TODO: wake only once the semaphore is ready
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! semaphore {
|
||||
($name: ident, $count: expr, $max: expr) => {
|
||||
|
|
Loading…
Reference in New Issue