[statechart] Pass event data to state constructor?
I'd like to be able to communicate the data from an event to the state(s) that get constructed as a result of a transition. I don't see an obvious way to do that, since the constructors of a state object either take only a context parameter (this is in an asychronous_state_machine), or also take a transition action plus an event. I can save the event data within the context object and then retrieve it post-construction, but that seems error-prone. Is there a better way to do this? Thanks, Bill
Hi Bill
I'd like to be able to communicate the data from an event to the state(s) that get constructed as a result of a transition.
That's a pretty common request, see item 3 on the to-do list: http://www.boost.org/libs/statechart/doc/future_and_history.html#ToDoList As stated in the todo-item, passing event data to the state constructor is not as straight-forward as it might seem. You are bound to lose event type-safety. However, if you have a compelling use-case, I'm willing to finally implement this feature. HTH & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
Hi Andreas, In the scenario I'm thinking of, we have an event which says "data is available" from a data source. We don't want to put the data itself in the event, because it's very large and/or very expensive to obtain, and it might or might not be of interest. Instead, the event contains a token that can be used to request the data if it turns out to be needed. So on receipt of that "data is available" event, we'll transition to a new state that can determine whether it needs to obtain the data or not, and if so, to use the token to get it. But as it stands now, the new state doesn't have access to the token. In the meantime, what would be a good way to approach this? The only option I can think of is to save the token somewhere so the destination state can get it. Thanks, Bill On Wed, Sep 2, 2009 at 11:47 AM, Andreas Huber < ahd6974-spamboostorgtrap@yahoo.com> wrote:
Hi Bill
I'd like to be able to communicate the data from an event to the state(s)
that get constructed as a result of a transition.
That's a pretty common request, see item 3 on the to-do list:
http://www.boost.org/libs/statechart/doc/future_and_history.html#ToDoList
As stated in the todo-item, passing event data to the state constructor is not as straight-forward as it might seem. You are bound to lose event type-safety. However, if you have a compelling use-case, I'm willing to finally implement this feature.
HTH & Regards,
-- Andreas Huber
When replying by private email, please remove the words spam and trap from the address shown in the header.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
In the scenario I'm thinking of, we have an event which says "data is available" from a data source. We don't want to put the data itself in the event, because it's very large and/or very expensive to obtain, and it might or might not be of interest. Instead, the event contains a token that can be used to request the data if it turns out to be needed. So on receipt of that "data is available" event, we'll transition to a new state that can determine whether it needs to obtain the data or not, and if so, to use the token to get it. But as it stands now, the new state doesn't have access to the token.
Ok. How do you determine whether you'll query the data source? Do you need to wait for more events or can this be determined with the token only? -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
This can be determined with the token, perhaps supplemented with queries to other objects. I should have mentioned that in our system this is a general pattern, with different token and data types that need to be responded to differently in different states - this is why it seems that the most reliable and general solution would be to pass the event data into the new state. It's true that this removes type safety, since I now have to dynamic_cast or equivalent in order to get to the actual data, but I'm not terribly worried about this (or, maybe more accurately, I don't see a better alternative). The idea of saving the event data somewhere worries me, since I would have to be careful that the new state picks up the data that's really meant for it, that there are no race conditions, that orthogonal states work correctly in this scenario (meaning multiple event objects have to be handled this way), etc. On Wed, Sep 2, 2009 at 2:00 PM, Andreas Huber < ahd6974-spamboostorgtrap@yahoo.com> wrote:
In the scenario I'm thinking of, we have an event which says "data is
available" from a data source. We don't want to put the data itself in the event, because it's very large and/or very expensive to obtain, and it might or might not be of interest. Instead, the event contains a token that can be used to request the data if it turns out to be needed. So on receipt of that "data is available" event, we'll transition to a new state that can determine whether it needs to obtain the data or not, and if so, to use the token to get it. But as it stands now, the new state doesn't have access to the token.
Ok. How do you determine whether you'll query the data source? Do you need to wait for more events or can this be determined with the token only?
-- Andreas Huber
When replying by private email, please remove the words spam and trap from the address shown in the header.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
This can be determined with the token, perhaps supplemented with queries to other objects.
Ok, in this case one easy option would be to make the query within the transition action. Contrary to the entry and exit actions, a transition action does have type-safe access to the triggering event. If other objects need to be queried then these could be accessed from the transition action as well. The data that is gathered in the query could be put into a new event which is passed to simple_state::post_event. The destination state would then define an in_state_reaction triggered by the new event. Or, if you want to make the query after entering the destination state: Repost the event carrying the token in the transition action and define an in-state reaction triggered by the same event. The in-state reaction would then execute the query and store the data in the destination state.
I should have mentioned that in our system this is a general pattern, with different token and data types that need to be responded to differently in different states - this is why it seems that the most reliable and general solution would be to pass the event data into the new state. It's true that this removes type safety, since I now have to dynamic_cast or equivalent in order to get to the actual data, but I'm not terribly worried about this (or, maybe more accurately, I don't see a better alternative).
See above, an alternative is the "transition action posts event that triggers an in-state reaction"-pattern (what a name :-)). With this pattern type-safety is upheld, at the cost of needing to process an additional event, which is probably negligible is your case. Another (IMO minor) problem is that you might need move some of the things that you planned to to in the destination state entry action to the in-state reaction. HTH, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
That does give us a couple of options. One or the other of these would certainly be fine for a case where relatively few events need to be handled in this way. I think, though, that it could add significant complexity to a large statechart where all or most reactions had to involve an indirection through a transition action plus possibly an additional in-state reaction. Though it would work, I think the extra mechanism would obscure the fundamental structure of the statechart. In our case, we have an additional option, since we have objects that live externally to the state objects and which get attached to them as they come and go. These external objects can offer an interface for setting/getting the triggering event; then each transit<xyz>() call can be preceded by a call that sets the event object, and if the event object is needed it will be available when xyz is constructed. This has some disadvantages - we lose type safety, of course, and we become dependent on these external objects to handle these situations - but we have a need for these external objects anyway, and this situation is so common in our case that at the moment it seems preferable to the option of adding additional actions/reactions to the statechart (which will already be fairly complex). So, I would still lobby for the addition of simple_state::triggering_event(), but we do have options in the meantime. Thanks, Bill On Thu, Sep 3, 2009 at 1:56 AM, Andreas Huber < ahd6974-spamboostorgtrap@yahoo.com> wrote:
This can be determined with the token, perhaps supplemented with queries to
other objects.
Ok, in this case one easy option would be to make the query within the transition action. Contrary to the entry and exit actions, a transition action does have type-safe access to the triggering event. If other objects need to be queried then these could be accessed from the transition action as well. The data that is gathered in the query could be put into a new event which is passed to simple_state::post_event. The destination state would then define an in_state_reaction triggered by the new event.
Or, if you want to make the query after entering the destination state: Repost the event carrying the token in the transition action and define an in-state reaction triggered by the same event. The in-state reaction would then execute the query and store the data in the destination state.
I should have mentioned that in our system this is a general pattern, with
different token and data types that need to be responded to differently in different states - this is why it seems that the most reliable and general solution would be to pass the event data into the new state. It's true that this removes type safety, since I now have to dynamic_cast or equivalent in order to get to the actual data, but I'm not terribly worried about this (or, maybe more accurately, I don't see a better alternative).
See above, an alternative is the "transition action posts event that triggers an in-state reaction"-pattern (what a name :-)). With this pattern type-safety is upheld, at the cost of needing to process an additional event, which is probably negligible is your case. Another (IMO minor) problem is that you might need move some of the things that you planned to to in the destination state entry action to the in-state reaction.
HTH,
-- Andreas Huber
When replying by private email, please remove the words spam and trap from the address shown in the header.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
So, I would still lobby for the addition of simple_state::triggering_event(), but we do have options in the meantime.
Ok, since this has been requested a couple of times now, I'll add this feature to the next release. Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
Excellent, thanks! And thanks for boost::statechart too. It's a great example of a sophisticated, complex implementation in the service of a convenient and expressive interface for clients. I've only begun looking at the implementation, but I've learned a lot from it already. Bill On Thu, Sep 3, 2009 at 10:11 PM, Andreas Huber < ahd6974-spamboostorgtrap@yahoo.com> wrote:
So, I would still lobby for the addition of
simple_state::triggering_event(), but we do have options in the meantime.
Ok, since this has been requested a couple of times now, I'll add this feature to the next release.
Regards,
-- Andreas Huber
When replying by private email, please remove the words spam and trap from the address shown in the header.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Andreas Huber
-
Bill Clark