Boost logo

Boost :

Subject: Re: [boost] [MSM] Interrupt anonymous transitions or blocking process_events?
From: anlmat (anlmat_at_[hidden])
Date: 2011-04-19 16:27:15

Hi Christophe,

Thank you for the helpful reply!


>> Perhaps I am going about this the wrong here and please tell me if it
>> can be done in some other much better way! I want to be able to have
>> automatic transitions that I can interrupt.
> You have to use run-to-completion. Base your design on short-terms
> events fed to the state machine, which triggers work and reacts to
> changes in forms of other events.
> In your case, one possibility would be to have the state machine
> delegate (post) some work upon state entry or transition action to a
> thread, then posting a new task upon state exit, etc.
> Make your state machine be serviced by only one thread, triggering
> work and reacting to events. Trust me on that one, having a state
> machine serviced by 2 threads is a good receipt for headaches ;-)
> If you know boost::asio, it's a bit like the async_xxx methods,
> trigger some work and get ready for the next action (which would be a
> callback, to continue with this asio example).

That helped me alot doing it that way. Thank you! It was a struggle
before I realized how to call a process_event(...) from within a member
function. I hope I am doing it the right way :-)

I also tried adding

boost::signals2::signal<void ()> sig;

to the statemachine but my compiler did not like that at all
(noncopyable errors). So I stayed with a mutex and a condition variable.
The way I did it can be improved I am sure...

Anyway, you can see an outline below of how I did this. Perhaps this is
an ok way doing it?


struct player_ : ...
   boost::mutex event_mutex_;
   boost::thread thread_;
   boost::condition_variable_any cond_;
   bool trigger_;

   void next_song();
   void playing_thread();
   //I choose to start the thread in the ctor...
   player_():thread_(boost::thread(&player_::playing_thread, this))

   struct play_song
     template <class EVT,class FSM,class SourceState,class TargetState>
     void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
       std::cout << "starting to play song "<< current_name_ <<std::endl;

       //triggers the thread to leave its waiting state
//in transition_table
//NextSong event is generated in the playing_thread
  Row < Playing , NextSong , Playing , play_song , exists_next >,
  Row < Playing , NextSong , Stopped , stop_playing , no_more_songs >,
  Row < Playing , Stop , Stopped , stop_playing >,
// Pick a back-end
typedef msm::back::state_machine<player_> player;


void player_::next_song()
   trigger_ = true;

void player_::playing_thread()
     boost::mutex::scoped_lock trigg_lock(trigg_mutex);

     trigger_ = false;
     //Simulate playing song...
     //The state machine can now react to other events like Stop()
     //for example.

     boost::mutex::scoped_lock lock(event_mutex_);
     //This is how you post a process_event from a member function.
     // note: the "player" here is not the same as "player_" !!
     // this "player" is the typedef choosen back-end name.




Boost list run by bdawes at, gregod at, cpdaniel at, john at