sml icon indicating copy to clipboard operation
sml copied to clipboard

Handle any event - kleene event

Open Quincunx271 opened this issue 6 years ago • 11 comments

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.

Quincunx271 avatar Oct 09 '18 18:10 Quincunx271

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,

drorspei avatar Feb 10 '19 22:02 drorspei

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.

Rijom avatar Sep 11 '20 20:09 Rijom

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?

drorspei avatar Sep 11 '20 20:09 drorspei

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 combining unexpected_event<_> with event<_> will result in catching all not handled events.

Rijom avatar Sep 12 '20 07:09 Rijom

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 avatar Sep 12 '20 17:09 erikzenker

@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 avatar Sep 12 '20 18:09 Rijom

@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.

erikzenker avatar Sep 12 '20 18:09 erikzenker

@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?

drorspei avatar Sep 12 '20 18:09 drorspei

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 avatar Sep 13 '20 20:09 Rijom

@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!!!

xorz57 avatar Feb 21 '23 12:02 xorz57

@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 don't recall seeing event<_> in the documentation too...

xorz57 avatar Feb 21 '23 12:02 xorz57