gen_statem: state and named timeouts, info events
Add the two timeout flavours, both surfacing as ordinary events matched in on-state arms: - cx.state_timeout(d): fires a state_timeout event after d in the current state, auto-reset by the loop on every real transition. - cx.timeout(name, d): fires a timeout(name) event after d, surviving state changes, keyed by name, with cx.cancel_timeout(name). Both ride the existing timer min-heap via send_after_to onto a new per-loop system channel, selected above the inbox so a fire can't be starved by inbox traffic. A local-id stamp on each fire lets a reset/cancel that loses the race discard a stale fire. The macro grows an info: clause and folds three internal Ev variants (Info, StateTimeout, Timeout) alongside cast/call, with new row keywords info / state_timeout / timeout. Unmatched info silently drops (the gen_server default); state/named timeouts have no default, so a state that can see one must handle it or the match is non-exhaustive. Rename the hand-written expansion-target example fused -> expanded, retire the deprecated Switch demo machine (its round-trip / enter / panic-down coverage moves onto the timer machine), and refresh the macro docs to the door machine. cargo build --all-targets warning-free; cargo test green.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! The **same** machine as `examples/gen_statem_fused.rs`, written through the
|
||||
//! The **same** machine as `examples/gen_statem_expanded.rs`, written through the
|
||||
//! `gen_statem!` macro. Diff this file against that one to see exactly what the
|
||||
//! macro buys: every `// ===` section there that was boilerplate (the `Ev`
|
||||
//! enum, the `DoorSm` struct, `start`, the whole `Machine` impl, the `enter`
|
||||
@@ -21,7 +21,7 @@ use smarm::gen_statem;
|
||||
use smarm::run;
|
||||
use smarm::gen_statem::Reply;
|
||||
|
||||
// === user types (identical to gen_statem_fused.rs) =========================
|
||||
// === user types (identical to gen_statem_expanded.rs) =========================
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum Door {
|
||||
@@ -87,7 +87,7 @@ fn on_unlock(key: u32) -> UnlockOutcome {
|
||||
|
||||
gen_statem! {
|
||||
machine: DoorSm { state: Door, data: Data };
|
||||
event: Ev { cast: Cast, call: Call };
|
||||
event: Ev { cast: Cast, call: Call, info: () };
|
||||
|
||||
// You name the bindings the bodies use; the macro can't lend you its own
|
||||
// `self`/`cx` across macro hygiene. `data` = &mut Data, `prev` = current
|
||||
@@ -117,6 +117,10 @@ gen_statem! {
|
||||
call Call::GetState(r) => { r.reply(prev); prev },
|
||||
call Call::GetEnters(r) => { r.reply(data.enters); prev },
|
||||
call Call::GetPushes(r) => { r.reply(data.pushes); prev },
|
||||
// This machine arms no timeouts, so refuse them everywhere. (Info has a
|
||||
// built-in silent-drop default, so it needs no row.)
|
||||
state_timeout => unhandled,
|
||||
timeout _ => unhandled,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +149,7 @@ fn main() {
|
||||
|
||||
// ===========================================================================
|
||||
// BREAK-CASE MENU — the four guarantees, through the macro. Each fires exactly
|
||||
// as it does in the hand-written gen_statem_fused.rs.
|
||||
// as it does in the hand-written gen_statem_expanded.rs.
|
||||
//
|
||||
// 1. ORPHAN HANDLER (dead_code -> error):
|
||||
// add `fn on_slam(_d: &mut Data) {}` and don't reference it.
|
||||
|
||||
Reference in New Issue
Block a user