aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhard de Clercq <[email protected]>2025-12-12 13:04:51 +0000
committerGerhard de Clercq <[email protected]>2025-12-12 15:34:57 +0000
commitb1fe9c6955ff857e3729a0bb4727247e050fb7ae (patch)
treeea6be7b3f900a4dc44b1c1a4ac104e4154cd3ec5
parent778bd76c1c2746ac9564132bcab0f8359feb7b13 (diff)
Add `run_until` function to std Executor as to support grafeul shutdown.
-rw-r--r--embassy-executor/CHANGELOG.md1
-rw-r--r--embassy-executor/src/arch/std.rs15
-rw-r--r--examples/std/src/bin/tick_cancel.rs47
3 files changed, 62 insertions, 1 deletions
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
15- Added optional "earliest deadline first" EDF scheduling 15- Added optional "earliest deadline first" EDF scheduling
16- Migrate `cortex-ar` to `aarch32-cpu`. The feature name `arch-cortex-ar` remains the same and 16- Migrate `cortex-ar` to `aarch32-cpu`. The feature name `arch-cortex-ar` remains the same and
17 legacy ARM architectures are not supported. 17 legacy ARM architectures are not supported.
18- Added `run_until` to `arch-std` variant of `Executor`.
18 19
19## 0.9.1 - 2025-08-31 20## 0.9.1 - 2025-08-31
20 21
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 {
55 /// 55 ///
56 /// This function never returns. 56 /// This function never returns.
57 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { 57 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
58 self.run_until(init, || false);
59 unreachable!()
60 }
61
62 /// Run the executor until a flag is raised.
63 ///
64 /// This function is identical to `Executor::run()` apart from offering a `done` flag to stop execution.
65 pub fn run_until(&'static mut self, init: impl FnOnce(Spawner), mut done: impl FnMut() -> bool) {
58 init(self.inner.spawner()); 66 init(self.inner.spawner());
59 67
60 loop { 68 loop {
61 unsafe { self.inner.poll() }; 69 unsafe { self.inner.poll() };
62 self.signaler.wait() 70
71 if done() {
72 break;
73 }
74
75 self.signaler.wait();
63 } 76 }
64 } 77 }
65 } 78 }
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 @@
1use std::sync::atomic::{AtomicBool, Ordering};
2use std::thread;
3use std::time::Duration;
4
5use embassy_executor::Executor;
6use embassy_time::Timer;
7use log::*;
8use static_cell::StaticCell;
9
10#[embassy_executor::task]
11async fn run() {
12 loop {
13 info!("tick");
14 Timer::after_secs(1).await;
15 }
16}
17
18static DONE: StaticCell<AtomicBool> = StaticCell::new();
19static EXECUTOR: StaticCell<Executor> = StaticCell::new();
20
21fn main() {
22 env_logger::builder()
23 .filter_level(log::LevelFilter::Debug)
24 .format_timestamp_nanos()
25 .init();
26
27 let done = DONE.init(AtomicBool::new(false));
28 let done_cb = || done.load(Ordering::Relaxed);
29
30 let server_thread = thread::spawn(move || {
31 let executor = EXECUTOR.init(Executor::new());
32 executor.run_until(
33 |spawner| {
34 spawner.spawn(run().unwrap());
35 },
36 done_cb,
37 );
38 info!("Executor finished");
39 });
40
41 thread::sleep(Duration::from_secs(5));
42
43 info!("Cancelling executor");
44 done.store(true, Ordering::Relaxed);
45
46 server_thread.join().unwrap();
47}