aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-06-25 21:17:56 +0000
committerGitHub <[email protected]>2023-06-25 21:17:56 +0000
commitd8c70c5c3e89a0a83ae58881fe0bed5071939b2e (patch)
tree2f39d018c2bb6e3acff1c9711f65aa2c68578048
parent03e0116a56d7bc4b8eb639fd590eaa186d039b2b (diff)
parent12872ce49b3945c1a28ae362f78bcfb334a9eeb8 (diff)
Merge pull request #1583 from bugadani/const
Allow path expressions as `task(pool_size)`
-rw-r--r--embassy-macros/Cargo.toml4
-rw-r--r--embassy-macros/src/lib.rs37
-rw-r--r--embassy-macros/src/macros/main.rs9
-rw-r--r--embassy-macros/src/macros/task.rs23
-rw-r--r--examples/nrf52840/src/bin/self_spawn.rs6
5 files changed, 51 insertions, 28 deletions
diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml
index 781026b99..3b8fe8b44 100644
--- a/embassy-macros/Cargo.toml
+++ b/embassy-macros/Cargo.toml
@@ -12,9 +12,9 @@ categories = [
12] 12]
13 13
14[dependencies] 14[dependencies]
15syn = { version = "1.0.76", features = ["full", "extra-traits"] } 15syn = { version = "2.0.15", features = ["full", "extra-traits"] }
16quote = "1.0.9" 16quote = "1.0.9"
17darling = "0.13.0" 17darling = "0.20.1"
18proc-macro2 = "1.0.29" 18proc-macro2 = "1.0.29"
19 19
20[lib] 20[lib]
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs
index ba4f13b77..c9d58746a 100644
--- a/embassy-macros/src/lib.rs
+++ b/embassy-macros/src/lib.rs
@@ -1,11 +1,28 @@
1#![doc = include_str!("../README.md")] 1#![doc = include_str!("../README.md")]
2extern crate proc_macro; 2extern crate proc_macro;
3 3
4use darling::ast::NestedMeta;
4use proc_macro::TokenStream; 5use proc_macro::TokenStream;
5 6
6mod macros; 7mod macros;
7mod util; 8mod util;
8use macros::*; 9use macros::*;
10use syn::parse::{Parse, ParseBuffer};
11use syn::punctuated::Punctuated;
12use syn::Token;
13
14struct Args {
15 meta: Vec<NestedMeta>,
16}
17
18impl Parse for Args {
19 fn parse(input: &ParseBuffer) -> syn::Result<Self> {
20 let meta = Punctuated::<NestedMeta, Token![,]>::parse_terminated(input)?;
21 Ok(Args {
22 meta: meta.into_iter().collect(),
23 })
24 }
25}
9 26
10/// Declares an async task that can be run by `embassy-executor`. The optional `pool_size` parameter can be used to specify how 27/// Declares an async task that can be run by `embassy-executor`. The optional `pool_size` parameter can be used to specify how
11/// many concurrent tasks can be spawned (default is 1) for the function. 28/// many concurrent tasks can be spawned (default is 1) for the function.
@@ -39,10 +56,10 @@ use macros::*;
39/// ``` 56/// ```
40#[proc_macro_attribute] 57#[proc_macro_attribute]
41pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { 58pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
42 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 59 let args = syn::parse_macro_input!(args as Args);
43 let f = syn::parse_macro_input!(item as syn::ItemFn); 60 let f = syn::parse_macro_input!(item as syn::ItemFn);
44 61
45 task::run(args, f).unwrap_or_else(|x| x).into() 62 task::run(&args.meta, f).unwrap_or_else(|x| x).into()
46} 63}
47 64
48/// Creates a new `executor` instance and declares an application entry point for Cortex-M spawning the corresponding function body as an async task. 65/// Creates a new `executor` instance and declares an application entry point for Cortex-M spawning the corresponding function body as an async task.
@@ -65,9 +82,9 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
65/// ``` 82/// ```
66#[proc_macro_attribute] 83#[proc_macro_attribute]
67pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream { 84pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream {
68 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 85 let args = syn::parse_macro_input!(args as Args);
69 let f = syn::parse_macro_input!(item as syn::ItemFn); 86 let f = syn::parse_macro_input!(item as syn::ItemFn);
70 main::run(args, f, main::cortex_m()).unwrap_or_else(|x| x).into() 87 main::run(&args.meta, f, main::cortex_m()).unwrap_or_else(|x| x).into()
71} 88}
72 89
73/// Creates a new `executor` instance and declares an application entry point for RISC-V spawning the corresponding function body as an async task. 90/// Creates a new `executor` instance and declares an application entry point for RISC-V spawning the corresponding function body as an async task.
@@ -100,9 +117,9 @@ pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream {
100/// ``` 117/// ```
101#[proc_macro_attribute] 118#[proc_macro_attribute]
102pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream { 119pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream {
103 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 120 let args = syn::parse_macro_input!(args as Args);
104 let f = syn::parse_macro_input!(item as syn::ItemFn); 121 let f = syn::parse_macro_input!(item as syn::ItemFn);
105 main::run(args.clone(), f, main::riscv(args)) 122 main::run(&args.meta, f, main::riscv(&args.meta))
106 .unwrap_or_else(|x| x) 123 .unwrap_or_else(|x| x)
107 .into() 124 .into()
108} 125}
@@ -127,9 +144,9 @@ pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream {
127/// ``` 144/// ```
128#[proc_macro_attribute] 145#[proc_macro_attribute]
129pub fn main_std(args: TokenStream, item: TokenStream) -> TokenStream { 146pub fn main_std(args: TokenStream, item: TokenStream) -> TokenStream {
130 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 147 let args = syn::parse_macro_input!(args as Args);
131 let f = syn::parse_macro_input!(item as syn::ItemFn); 148 let f = syn::parse_macro_input!(item as syn::ItemFn);
132 main::run(args, f, main::std()).unwrap_or_else(|x| x).into() 149 main::run(&args.meta, f, main::std()).unwrap_or_else(|x| x).into()
133} 150}
134 151
135/// Creates a new `executor` instance and declares an application entry point for WASM spawning the corresponding function body as an async task. 152/// Creates a new `executor` instance and declares an application entry point for WASM spawning the corresponding function body as an async task.
@@ -152,7 +169,7 @@ pub fn main_std(args: TokenStream, item: TokenStream) -> TokenStream {
152/// ``` 169/// ```
153#[proc_macro_attribute] 170#[proc_macro_attribute]
154pub fn main_wasm(args: TokenStream, item: TokenStream) -> TokenStream { 171pub fn main_wasm(args: TokenStream, item: TokenStream) -> TokenStream {
155 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 172 let args = syn::parse_macro_input!(args as Args);
156 let f = syn::parse_macro_input!(item as syn::ItemFn); 173 let f = syn::parse_macro_input!(item as syn::ItemFn);
157 main::run(args, f, main::wasm()).unwrap_or_else(|x| x).into() 174 main::run(&args.meta, f, main::wasm()).unwrap_or_else(|x| x).into()
158} 175}
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs
index 5c099f68a..7c4d55163 100644
--- a/embassy-macros/src/macros/main.rs
+++ b/embassy-macros/src/macros/main.rs
@@ -1,3 +1,4 @@
1use darling::export::NestedMeta;
1use darling::FromMeta; 2use darling::FromMeta;
2use proc_macro2::TokenStream; 3use proc_macro2::TokenStream;
3use quote::quote; 4use quote::quote;
@@ -11,8 +12,8 @@ struct Args {
11 entry: Option<String>, 12 entry: Option<String>,
12} 13}
13 14
14pub fn riscv(args: syn::AttributeArgs) -> TokenStream { 15pub fn riscv(args: &[NestedMeta]) -> TokenStream {
15 let maybe_entry = match Args::from_list(&args) { 16 let maybe_entry = match Args::from_list(args) {
16 Ok(args) => args.entry, 17 Ok(args) => args.entry,
17 Err(e) => return e.write_errors(), 18 Err(e) => return e.write_errors(),
18 }; 19 };
@@ -77,9 +78,9 @@ pub fn std() -> TokenStream {
77 } 78 }
78} 79}
79 80
80pub fn run(args: syn::AttributeArgs, f: syn::ItemFn, main: TokenStream) -> Result<TokenStream, TokenStream> { 81pub fn run(args: &[NestedMeta], f: syn::ItemFn, main: TokenStream) -> Result<TokenStream, TokenStream> {
81 #[allow(unused_variables)] 82 #[allow(unused_variables)]
82 let args = Args::from_list(&args).map_err(|e| e.write_errors())?; 83 let args = Args::from_list(args).map_err(|e| e.write_errors())?;
83 84
84 let fargs = f.sig.inputs.clone(); 85 let fargs = f.sig.inputs.clone();
85 86
diff --git a/embassy-macros/src/macros/task.rs b/embassy-macros/src/macros/task.rs
index 9f30cf43e..1d30434e9 100644
--- a/embassy-macros/src/macros/task.rs
+++ b/embassy-macros/src/macros/task.rs
@@ -1,20 +1,24 @@
1use darling::export::NestedMeta;
1use darling::FromMeta; 2use darling::FromMeta;
2use proc_macro2::TokenStream; 3use proc_macro2::{Span, TokenStream};
3use quote::{format_ident, quote}; 4use quote::{format_ident, quote};
4use syn::{parse_quote, ItemFn, ReturnType, Type}; 5use syn::{parse_quote, Expr, ExprLit, ItemFn, Lit, LitInt, ReturnType, Type};
5 6
6use crate::util::ctxt::Ctxt; 7use crate::util::ctxt::Ctxt;
7 8
8#[derive(Debug, FromMeta)] 9#[derive(Debug, FromMeta)]
9struct Args { 10struct Args {
10 #[darling(default)] 11 #[darling(default)]
11 pool_size: Option<usize>, 12 pool_size: Option<syn::Expr>,
12} 13}
13 14
14pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, TokenStream> { 15pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result<TokenStream, TokenStream> {
15 let args = Args::from_list(&args).map_err(|e| e.write_errors())?; 16 let args = Args::from_list(args).map_err(|e| e.write_errors())?;
16 17
17 let pool_size: usize = args.pool_size.unwrap_or(1); 18 let pool_size = args.pool_size.unwrap_or(Expr::Lit(ExprLit {
19 attrs: vec![],
20 lit: Lit::Int(LitInt::new("1", Span::call_site())),
21 }));
18 22
19 let ctxt = Ctxt::new(); 23 let ctxt = Ctxt::new();
20 24
@@ -45,10 +49,6 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
45 }, 49 },
46 } 50 }
47 51
48 if pool_size < 1 {
49 ctxt.error_spanned_by(&f.sig, "pool_size must be 1 or greater");
50 }
51
52 let mut arg_names = Vec::new(); 52 let mut arg_names = Vec::new();
53 let mut fargs = f.sig.inputs.clone(); 53 let mut fargs = f.sig.inputs.clone();
54 54
@@ -82,7 +82,8 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
82 let mut task_outer: ItemFn = parse_quote! { 82 let mut task_outer: ItemFn = parse_quote! {
83 #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> { 83 #visibility fn #task_ident(#fargs) -> ::embassy_executor::SpawnToken<impl Sized> {
84 type Fut = impl ::core::future::Future + 'static; 84 type Fut = impl ::core::future::Future + 'static;
85 static POOL: ::embassy_executor::raw::TaskPool<Fut, #pool_size> = ::embassy_executor::raw::TaskPool::new(); 85 const POOL_SIZE: usize = #pool_size;
86 static POOL: ::embassy_executor::raw::TaskPool<Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new();
86 unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#arg_names,)*)) } 87 unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#arg_names,)*)) }
87 } 88 }
88 }; 89 };
diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs
index 196255a52..31ea6c81e 100644
--- a/examples/nrf52840/src/bin/self_spawn.rs
+++ b/examples/nrf52840/src/bin/self_spawn.rs
@@ -7,7 +7,11 @@ use embassy_executor::Spawner;
7use embassy_time::{Duration, Timer}; 7use embassy_time::{Duration, Timer};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::task(pool_size = 2)] 10mod config {
11 pub const MY_TASK_POOL_SIZE: usize = 2;
12}
13
14#[embassy_executor::task(pool_size = config::MY_TASK_POOL_SIZE)]
11async fn my_task(spawner: Spawner, n: u32) { 15async fn my_task(spawner: Spawner, n: u32) {
12 Timer::after(Duration::from_secs(1)).await; 16 Timer::after(Duration::from_secs(1)).await;
13 info!("Spawning self! {}", n); 17 info!("Spawning self! {}", n);