4

I want to use boost msm state machine but i am having a hard time imagining how it works. Let say we only have 2 states (s1, s2) and to go from s1 to s2 you need event e1 to be fired and to bo back you need another one e2. e1 and e2 can only be fired from within s1 and s2 respectively.

Now in main() I start by starting the statemachine (start()) then ill have a while loop that every 1 min will go back to the state machine but have to pick up from where it left.i.e.

main()
{
 MSM.start(); //start state machine

 while (a_condition)
 {
 ProcessInputsfromIO();
 Go_backtoStatemachine(); //how can i do this?
 delay(1min)
 }
 MSM.stop();
}

So basically when a state finishes executing, the statemachine will exit, then ill have a delay of 1 minutes, then the while loop will need to take me back to the state I was before I exit, or I think that's how we should implement a state machine.

Is what I am asking for out of the ordinary? If yes then how do people implement a non-blocking state machine? if no, then how can I implement Go_backtoStatemachine()?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Kam
  • 5,878
  • 10
  • 53
  • 97
  • Obviously the state on the state machine persists in between calls like start() and process_event(). The state machine doesn't exit after a call like start(), it 'exits' (or better, it terminates) only when it reaches the terminate state. – AndrewBloom Feb 17 '21 at 13:00

2 Answers2

3

There is a fairly simple example here:

MSM Simple Tutorial

A state machine is an abstract concept. It has states, events, etc. It does not really have a concept of blocking, non blocking, etc. Within the framework of Boost MSM you can call start() to enter the initial state, process_event() to inject events, and stop() to stop. The state machine simply captures system state and can call some functions as the system changes state. How you would use it is very application dependant.

Guy Sirton
  • 8,331
  • 2
  • 26
  • 36
  • So there's no way for me to exit a state and then re-enter it without going through the init state? – Kam Mar 05 '12 at 02:07
  • @user1248779: You can move between any state and back and also have an event make the state machine stay at the same state. You just need to have the right transition table. Study the example a bit more carefully. E.g. notice when you get a stop event in the stopped state you remain in the stop state. When you keep getting the open_close event you will transition between Empty and Open states - continuously. – Guy Sirton Mar 05 '12 at 02:41
  • Guy, thank you for your help you have no idea how much I'm appreciating this. But maybe I didn't explain myself properly. Moving between states and even staying in the same state is no problem IF I never exit the state machine. But let's say I am in state S1, and I exit from S1 and basically exit from the state machine (but i don't stop it), the only way I can reenter the state machine is by firing an event. So If I design the state table properly, maybe Ill add an event to every state that takes you back to the same state and at the end of my while loop ill just call that event? – Kam Mar 05 '12 at 03:11
  • What do you mean when you say "exit" the state machine. The state machine is an object that captures states and responds to events. While UML does allow for "exiting" a state machine just start by thinking about the state machine as never exiting. That doesn't mean you need to handle all events in all states though, look at the example, not all states handle all events. Tell me more about what you're trying to do and I can try and suggest something more concrete... – Guy Sirton Mar 05 '12 at 04:33
  • I basically need to implement the piece of code that I wrote in my original post, I will have a while loop and everytime I call Go_backtoStatemachine() I need to go back to the state where I left off and execute the state again. I will keep doing this until some IO change (ProcessInputsfromIO()) then the state will realise that the IO condition changed and will fire an event to go to another state at that point the entire thing repeats again. Please let me know if I need to be clearer. – Kam Mar 05 '12 at 06:36
  • So Im asking to go back to the same state I "exited" from its because I am planning to execute a state every 1 min, and if the state didn't fire an event to leave the state then Ill stay in that state and loop it every 1 min. – Kam Mar 05 '12 at 06:48
  • @user1248779: If you want to go back to some particular state, in a sense "reset" the state machine, you can stop() and start() it or you can add a "reset" event. If all you're doing though is processing one event and going back, why do you need a state machine? What is your application, i.e. what are you trying to accomplish? – Guy Sirton Mar 05 '12 at 07:29
  • I am reading IO from RS232, and depending on combination of inputs I am trying to define a set of possible outputs. No, Im not trying to reset the State Machine, Im trying to do to oposite, I want to be able to execute each state repeateadly until it fires an event and then itll go to another state and that will execuse repeatedly and so on..I just want a nice way to go back to state after I have finised executing it. – Kam Mar 05 '12 at 07:55
  • @user1248779: If you just want a fixed mapping from input to output use a table: out = table[in]. If you want to change states use a state machine with process_event() and use the entry functions to set your outputs if required. Does this make sense? – Guy Sirton Mar 05 '12 at 08:17
  • Yes that makes sense but every state can do different processing on the IO. Ok to reformulate, I just need a way to be able to go back to the state I was in prior from exiting from it :) Because once you exit from a state you can't go back to it unless an event took you to it, but since Im not within any state when I exit from the state I can't see how i can come back to it. – Kam Mar 05 '12 at 08:23
  • @Kam: Sounds like you just need a switch(in) {}. If you're not moving between states you really don't need a state machine. If you really want to move to the initial state stop() and then start(). – Guy Sirton Mar 05 '12 at 08:26
0

MSM has not any knowledge of threads, so when start() or process_event(MyEvent()) are called, they are executed on the current thread. It's possible to defer the event processing to a later moment though (which is still NOT thread-safe), as explained on the docs (https://www.boost.org/doc/libs/1_75_0/libs/msm/doc/HTML/ch03s05.html#d0e2668):

Enqueueing events for later processing

Calling process_event(Event const&) will immediately process the event with run-to-completion semantics. You can also enqueue the events and delay their processing by calling enqueue_event(Event const&) instead. Calling execute_queued_events() will then process all enqueued events (in FIFO order). Calling execute_single_queued_event() will execute the oldest enqueued event.

You can query the queue size by calling get_message_queue_size().

In the question's example then, you can

  1. enqueue the events inside ProcessInputsfromIO as
void ProcessInputsfromIO(){
    somethingToDo();
    myfsm.enqueue_event(myEvent1());
    somethingElseToDo();
    etc();
}
  1. Go_backtoStatemachine() becomes simply myfsm.execute_queued_events()
AndrewBloom
  • 2,171
  • 20
  • 30