From b1fe9c6955ff857e3729a0bb4727247e050fb7ae Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:04:51 +0000 Subject: Add `run_until` function to std Executor as to support grafeul shutdown. --- embassy-executor/CHANGELOG.md | 1 + embassy-executor/src/arch/std.rs | 15 +++++++++++- examples/std/src/bin/tick_cancel.rs | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 examples/std/src/bin/tick_cancel.rs diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 5fbb8cf13..8f1db7de7 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added optional "earliest deadline first" EDF scheduling - Migrate `cortex-ar` to `aarch32-cpu`. The feature name `arch-cortex-ar` remains the same and legacy ARM architectures are not supported. +- Added `run_until` to `arch-std` variant of `Executor`. ## 0.9.1 - 2025-08-31 diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs index c62ab723b..d4057144e 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -55,11 +55,24 @@ mod thread { /// /// This function never returns. pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { + self.run_until(init, || false); + unreachable!() + } + + /// Run the executor until a flag is raised. + /// + /// This function is identical to `Executor::run()` apart from offering a `done` flag to stop execution. + pub fn run_until(&'static mut self, init: impl FnOnce(Spawner), mut done: impl FnMut() -> bool) { init(self.inner.spawner()); loop { unsafe { self.inner.poll() }; - self.signaler.wait() + + if done() { + break; + } + + self.signaler.wait(); } } } diff --git a/examples/std/src/bin/tick_cancel.rs b/examples/std/src/bin/tick_cancel.rs new file mode 100644 index 000000000..54e44790f --- /dev/null +++ b/examples/std/src/bin/tick_cancel.rs @@ -0,0 +1,47 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread; +use std::time::Duration; + +use embassy_executor::Executor; +use embassy_time::Timer; +use log::*; +use static_cell::StaticCell; + +#[embassy_executor::task] +async fn run() { + loop { + info!("tick"); + Timer::after_secs(1).await; + } +} + +static DONE: StaticCell = StaticCell::new(); +static EXECUTOR: StaticCell = StaticCell::new(); + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Debug) + .format_timestamp_nanos() + .init(); + + let done = DONE.init(AtomicBool::new(false)); + let done_cb = || done.load(Ordering::Relaxed); + + let server_thread = thread::spawn(move || { + let executor = EXECUTOR.init(Executor::new()); + executor.run_until( + |spawner| { + spawner.spawn(run().unwrap()); + }, + done_cb, + ); + info!("Executor finished"); + }); + + thread::sleep(Duration::from_secs(5)); + + info!("Cancelling executor"); + done.store(true, Ordering::Relaxed); + + server_thread.join().unwrap(); +} -- cgit