fix: clear sub-SM defer queue when composite state is re-entered (#253)#705
Merged
kris-jusiak merged 2 commits intoMay 30, 2026
Merged
Conversation
boost-ext#253) Deferred events enqueued inside a sub-SM's lifetime were silently retained across exit. On re-entry the sub-SM's defer_ queue was not cleared by update_composite_states, so any event deferred in a prior session would fire spuriously on the next internal transition that triggers process_defer_events. Root cause: each sm_impl holds its own defer_ (same policy as the root, propagated through TPolicies). update_composite_states resets current_state_[] via initialize() but never touched defer_. Fix: add clear_deferred_events() to sm_impl, tag-dispatched on is_same<defer_t, no_policy> so it compiles for SMs without a defer_queue policy. Call it in both overloads of update_composite_states (history and non-history) so the defer queue is always emptied when a composite state is (re-)entered.
…ransition (boost-ext#643) Users working with sub-SMs sometimes need explicit control over the defer queue — for example, to discard stale events when exiting a sub-SM via a specific transition rather than relying on automatic cleanup. Adds front::actions::clear_defer (exposed as the sml::clear_defer global action object, alongside sml::defer and sml::process), which calls sm_impl::clear_deferred_events() on the current SM when the action fires. Usage: state<Nested> + event<EXIT> / clear_defer = "Init"_s Verified GCC/Clang C++14/17/20 and MSVC 19.51 C++20.
2716c08 to
8947e1f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Commit 1 — fix: clear sub-SM defer queue on composite re-entry (#253)
Root cause: Each
sm_implholds its owndefer_queue (same policy as the root, propagated viaTPolicies).process_defer_eventsreplays events from this queue on the next internal transition inside the sub-SM.update_composite_statesresetscurrent_state_[]viainitialize()when a composite is entered, but never cleareddefer_. Events deferred in a prior session fired spuriously on the first internal transition of the next session.Fix: Added
clear_deferred_events()tosm_impl, tag-dispatched onis_same<defer_t, no_policy>for C++14 compatibility. Called in bothupdate_composite_statesoverloads (history and non-history) so the defer queue is always emptied when a composite state is (re-)entered.Tests:
test/ft/issue_253_defer_clear_on_exit.cpp— 3 cases: stale event must not fire after exit + re-entry + round-trip; normal deferral still works within a session; no spurious fires without prior deferral.Commit 2 — feat: add
sml::clear_deferaction (#643)Exposes the new
clear_deferred_events()infrastructure as a user-accessible action object (sml::clear_defer, alongsidesml::deferandsml::process). Lets users explicitly discard pending deferred events on a specific outgoing transition:state<Nested> + event<EXIT> / clear_defer = "Init"_sTests:
test/ft/issue_643_clear_defer_action.cpp— user-controlled clear discards stale deferred events; no-op on empty queue.Verified: GCC 14 + Clang 18, C++14/17/20 (39–40/40 tests pass). MSVC 19.51 C++20 clean.