boost-ext / sml

C++14 State Machine library
https://boost-ext.github.io/sml
Boost Software License 1.0
1.12k stars 177 forks source link

bug: Events triggered via `sml::back::process<TEvent>()` are not processed in parent state #562

Open rhaschke opened 1 year ago

rhaschke commented 1 year ago

Expected Behavior

Events not handled in a child state should be handled by the parent state. Duplicate of #400.

Actual Behavior

While this works for events injected via process_event() from the top-level machine, it fails for events triggered by an action via sml::back::process<TEvent>(): https://godbolt.org/z/dnMv1dfa4

rhaschke commented 1 year ago
I analyzed this issue a little bit and found that the event triggered via sml::back::processs is injected into the sub state's process queue instead of using the root state's one: back::process process
https://github.com/boost-ext/sml/blob/4be9dd6b8e322acb6348f1b05655b3c276e54fb1/include/boost/sml.hpp#L1873 https://github.com/boost-ext/sml/blob/4be9dd6b8e322acb6348f1b05655b3c276e54fb1/include/boost/sml.hpp#L2128

A similar issue was resolved in #302 for process, which actually works correctly now. I added a (failing) unit test in my fork to illustrate the problem.

To resolve that issue here in a similar fashion, one would need to access the root sm in get_arg, which is not available yet. However, instead of applying this kind of fix again, I want to fundamentally question the design: Why do we need the process_ queue in all sub state machines at all? Doesn't it suffice to have a single one in the root state machine - as we need to process all events from there? All subs could simply have a pointer to that single queue instance, such that we don't need to change API of get_arg.

For deferred events the story is different I think: they should be kept in state-local queues and be processed as soon as the state is left.

vasdal commented 1 month ago

I also came across this problem, would be great if there exist a solution to this.

623 also has the same question.