sml
sml copied to clipboard
Handle any event - kleene event
How do I handle any event? I didn't see anything in the documentation for a kleene event like what Boost MSM has. The closest I could find is unexpected_event<_>
, but that only responds to events not mentioned in the transition table.
An example (modified from an SML example I found somewhere): https://godbolt.org/z/2yanqF . The goal is that, if I am in the state with a kleene event transition, process_event(anything{})
would trigger that transition, preferably with a lower priority than the other transitions.
I think you can use event<_>
, which responds to events mentioned in the transition table. So, for those mentioned and those not mentioned, you can have both transitions. Like so:
* "Disconnected"_s + event<_> / establish = "Connecting"_s,
"Disconnected"_s + unexpected_event<_> / establish = "Connecting"_s,
This seems to work in the example you put up. I'm not sure if the priorities are always like this, but adding the following line in the table works as expected:
"Disconnected"_s + event<connect> / ([]{ std::puts("priority yo!"); }, establish) = "Connecting"_s,
The unexpected_event<_>
is explained in the tutorial. It seems to contradict your statement above.
I have not seen the event<_>
. Is this mentioned anywhere? I think this definitely should be clarified and added to the documentation.
Hej! It's been a while since I've been here ^_^ (changed jobs, no c++ now :( )
I can't find the contradiction, can you elaborate?
I don't remember how I came up with the event<_>
idea, but I don't see it now in the tutorial. Have you checked if it still works?
Oh no! ;)
My understanding is the following:
- The docs say
unexpected_event<_>
catches all not handled events. - You on the other hand say
unexpected_event
catches all not handled events that are also not mentioned in the transition table. Only combiningunexpected_event<_>
withevent<_>
will result in catching all not handled events.
I never understood the existance of 'unexpected_event' since it catches usage errors of your state machine. Imho these kind of errors should only be handled at compile time.
@erikzenker An uncaught event isn't necessarily a usage error. I often have events triggered from external sources that might be too late and therefore will, intentionally, no longer be caught. For debugging purposes it could be nice to be able to add a some dedicated log message on any uncaught_event. (Provided they really work as expected. :smile: )
@Rijom I think you missunderstood the semantics of 'unexpected_event'. It is triggered for unknown events/types. So for events which are not defined in your transition table e.g.: calling process event on int. It is not the same which is known from the unexpected event handler of the msm. You could just check the return value of 'process_event' which will return false on an unprocessed event.
@Rijom it sounds like the case you have is most correctly solved using event<_>
, and without unexpected_event<_>
, and I would posit that the names even make sense: you are in fact expecting these events to be sent sometimes.
It's true that the tutorial doesn't mention event<_>
, and I'm not sure it still works. Did you check it? If it does, would you be willing to submit a pull request to add this to the docs?
I see - thanks for the explanation. Though I'm not convinced this is the best possible behaviour.
Also I wonder what defines an unexpected_event
in the context of a composite state-machine. Will an event used in the child state-machine count as unknown when triggered in the parent?
I'll see if I find some time to figure out how exactly this works and try to improve the wording in the tutorial.
@Rijom I think you missunderstood the semantics of 'unexpected_event'. It is triggered for unknown events/types. So for events which are not defined in your transition table e.g.: calling process event on int. It is not the same which is known from the unexpected event handler of the msm. You could just check the return value of 'process_event' which will return false on an unprocessed event.
Checking the return value of process_event(...)
was just what I needed in my case 👍 . Thanks a lot!!!
@Rijom it sounds like the case you have is most correctly solved using
event<_>
, and withoutunexpected_event<_>
, and I would posit that the names even make sense: you are in fact expecting these events to be sent sometimes.It's true that the tutorial doesn't mention
event<_>
, and I'm not sure it still works. Did you check it? If it does, would you be willing to submit a pull request to add this to the docs?
I don't recall seeing event<_>
in the documentation too...