Skip to content

Commit 6573d17

Browse files
committed
[api]: Add the macros about invoking async function in the normal function.
1 parent 1545574 commit 6573d17

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

ulib/axasync-std/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#![feature(doc_cfg)]
77
#![feature(doc_auto_cfg)]
88

9+
#[macro_use]
10+
mod macros;
911
pub mod task;
1012

1113
mod io {

ulib/axasync-std/src/macros.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//! Async Standard library macros
2+
3+
/// The `block_on!` macro which is used to poll a async function in a busy spinning manner.
4+
///
5+
/// This macro is used in the normal function. In the async function, the future can be direcyly invoked.
6+
///
7+
/// Usage scenarios: when the future can be polled without waiting or the waiting for a short time, it should use this macro.
8+
///
9+
/// Examples:
10+
///
11+
/// ```rust
12+
/// fn main() {
13+
/// block_on!{hello_world()};
14+
/// }
15+
///
16+
/// async fn hello_world() {
17+
/// println!("hello world!");
18+
/// }
19+
/// ```
20+
///
21+
#[macro_export]
22+
macro_rules! block_on {
23+
($l:expr) => {
24+
// The future can be pinned on the stack directly
25+
// because the stack cannot be used by other task.
26+
let mut future = $l;
27+
let mut pinned_fut = unsafe { core::pin::Pin::new_unchecked(&mut future) };
28+
// The waker can use the `Waker::noop()` because
29+
// there is no task switching while polling the future.
30+
// The task which call this macro and poll this future can
31+
// be preempt by the timer IRQ.
32+
let waker = core::task::Waker::noop();
33+
let mut cx = core::task::Context::from_waker(&waker);
34+
loop {
35+
if let core::task::Poll::Ready(res) = pinned_fut.as_mut().poll(&mut cx) {
36+
break res;
37+
}
38+
}
39+
};
40+
}
41+
42+
/// The `callasync!` macro is the same as the `block_on!`,
43+
/// but it is combined with thread switching.
44+
///
45+
/// This macro is used in the normal function.
46+
/// In the async function, the future can be direcyly invoked.
47+
///
48+
/// Usage scenarios:
49+
/// when the future need wait for a long time to be `Poll::Ready`,
50+
/// and the thread must wait for the result of the future,
51+
/// it should use this macro.
52+
/// It can yield the thread to run other task.
53+
///
54+
/// The yield operation can be defined through a `trait`
55+
/// which is as the same as the implementation in
56+
/// [`axlog`](https://github.com/arceos-org/arceos/tree/main/modules/axlog) crate.
57+
58+
/// Examples:
59+
/// ```rust
60+
/// fn main() {
61+
/// callasync!{test()};
62+
/// }
63+
///
64+
/// async fn test() -> i32 {
65+
/// let mut flag = false;
66+
/// core::future::poll_fn(|_cx| {
67+
/// if !flag {
68+
/// flag = true;
69+
/// core::task::Poll::Pending
70+
/// } else {
71+
/// core::task::Poll::Ready(())
72+
/// }
73+
/// }).await;
74+
/// 43
75+
/// }
76+
/// ```
77+
#[macro_export]
78+
macro_rules! callasync {
79+
($l:expr) => {
80+
// The future can be pinned on the stack directly
81+
// because the stack cannot be used by other task.
82+
let mut future = $l;
83+
let mut pinned_fut = unsafe { core::pin::Pin::new_unchecked(&mut future) };
84+
// The waker can use the `Waker::noop()` because
85+
// the task is switched as a thread.
86+
// The task which call this macro and poll this future can
87+
// be preempt by the timer IRQ.
88+
let waker = core::task::Waker::noop();
89+
let mut cx = core::task::Context::from_waker(&waker);
90+
loop {
91+
match pinned_fut.as_mut().poll(&mut cx) {
92+
core::task::Poll::Ready(r) => break r,
93+
core::task::Poll::Pending => {
94+
// Yield the task which call this marco when the future return `Pending`.
95+
$crate::task::_api::ax_yield_now();
96+
}
97+
}
98+
}
99+
};
100+
}

ulib/axasync-std/src/task/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,8 @@ pub async fn sleep(dur: core::time::Duration) {
3636
pub async fn sleep_until(deadline: arceos_api::time::AxTimeValue) {
3737
api::ax_sleep_until_f(deadline).await;
3838
}
39+
40+
#[doc(hidden)]
41+
pub mod _api {
42+
pub use arceos_api::task::ax_yield_now;
43+
}

0 commit comments

Comments
 (0)