|
Boost : |
Subject: Re: [boost] [MSM] Comparison with ad-hoc FSM implementation
From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2009-12-10 12:16:41
Christophe Henry wrote:
> I fully agree with Michael's point that more complicated constructs
> are really messy to implement with ad-hoc techniques.
Do we have any concrete examples of larger problems anywhere? I would
be interested to see them so that I can consider how I would implement them.
> But on the construct presented by Phil I personally find a lot to criticize.
> First of all, it is a mess.
I would be much happier if you could please avoid using language like this.
> what really bugs me is the mix of fsm structure with
> character processing.
But in this application, the FSM is driven by the characters that are
received - that is what it is all about. Why do you want to separate
it out into two things?
> This is made even worse by the fact that this is obviously GUI code
> and such processing must happen several times in different modules.
As it happens, the application that I wrote this for is not a GUI app.
If it were, I still don't follow your comment about the code being used
many times.
> I also don't like:
>
>>void process_event(const character_received_event& e) { ....
>>void process_event(const sigwinch_event& e) { ....
>
> Having to write overloads in a template word??? No, thanks!
Can you please explain why ?
>>row < normal, character_received_event, seen_escape, none, &is_escape_char >,
>>row < normal, character_received_event, normal, &insert_at_cursor_and_advance >,
>>row < seen_escape, character_received_event, normal, &cursor_home, &is_H >,
>>row < seen_escape, character_received_event, normal, none >,
>>row < any, sigwinch_event, unchanged, &resize_screen >
>
> Apart from the fsm structure and syntax errors, which are irrelevant
> to the discussion, yes, I could do something like this if performance
> were uncritical in this part of the application and I wanted a chance
> to play with eUML. But more likely, I wouldn't do that.
> Instead, if performance was an issue I'd probably keep the second
> switch/case (the switch on character), pack it inside a nice generic
> functor which would in no case do this:
>
>>case escape: state = seen_escape; break;
>
> Because this means mixing character processing with fsm structure.
I still don't follow why you feel the need to make this separation.
> It'd be something like (as entry functor. Could be as transition functor too):
> struct CharTypeProcessing: euml_action<CharTypeProcessing>
> {
> template <class Event,class FSM,class STATE>
> void operator()(Event const&,FSM& fsm,STATE& )
> {
> switch (c) {
> case escape: fsm.process_event(escape_char()); break;
> .... more special characters like tab, newline etc ....
> default: fsm.process_event(normal_char(c) ) ;break;
> }
> }
> };
>
> I don't go more into details but I'm sure you get the idea.
Consider the transition from the seen_escape state to the normal state,
which occurs at the end of an escape sequence. For this you would need
a last_char_of_escape_sequence event. You would need to consider this
in your case statement above (e.g. letters normally do terminate the
escape sequence but digits normally don't). But this categorisation
happens for received characters whatever state the machine is currently
in. So in the transition table you would need rules like this:
row < normal, escape_char, seen_escape >,
row < normal, last_char_of_escape_sequence, normal >,
row < normal, not_last_char_of_escape_sequence, normal >,
row < seen_escape, escape_char, seen_escape >,
row < seen_escape, last_char_of_escape_sequence, normal >,
row < seen_escape, not_last_char_of_escape_sequence, seen_escape >,
i.e. every state has to enumerate every character category. With my
structure, I used an appropriate classification of the characters for
each state, which reduced the number of combinations that I had to deal with.
Regards,
Phil.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk