#[task]Expand description
Declare a static async (cooperative-tier) task. See the [task] module
docs and the crate-level example. Lives in the macro namespace, so it
coexists with the task module (rivet::task::TaskCell etc.) at the
same path.
Declare a static async task.
The annotated function must be async fn name() { ... } — no
parameters (shared state goes through statics, matching the usual
embedded pattern for peripherals/queues). The body may freely use
.await — Sleep, Semaphore::acquire(), Channel::send()/recv()
all work as real futures polled by the executor.
§Attributes
priority(required): Task priority (0 = lowest, 31 = highest).stack(optional): bytes reserved for the future’s state machine (default 512). Increase this if you get a “task future exceeds reserved stack size” panic at boot.
§Example
#[rivet::task(priority = 1, stack = 256)]
async fn blinky() {
loop {
rivet::time::Sleep::<500_000>::new().await; // 500ms
toggle_led();
}
}§How it works
F (the compiler-generated Future type of an async fn) is
unnameable on stable Rust, so it can’t appear in a static’s type.
Instead the macro declares static CELL: TaskCell<STACK_SIZE>
(STACK_SIZE is just a usize, always nameable) and generates a
thin non-generic wrapper function that calls the crate’s generic
TaskCell::poll::<F>, letting the compiler monomorphize the actual
future read/write per task without ever needing to write F down.