### Test State Machine Event Processing and Transitions Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SimpleWithFunctors2 Comprehensive test function that demonstrates state machine initialization, event processing, and state transitions. It exercises various paths through the state machine including starting, opening/closing, inserting disks, playing, pausing, and stopping, verifying the state after each operation. ```cpp void test() { player p; p.start(); p.process_event(open_close()); pstate(p); p.process_event(open_close()); pstate(p); p.process_event(cd_detected("louie, louie",DISK_DVD)); pstate(p); p.process_event(cd_detected("louie, louie",DISK_CD)); pstate(p); p.process_event(pause()); pstate(p); p.process_event(end_pause()); pstate(p); p.process_event(pause()); pstate(p); p.process_event(stop()); pstate(p); p.process_event(stop()); pstate(p); } ``` -------------------------------- ### Implement Action for Starting Playback in C++ Boost.MSM Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/OrthogonalDeferredPuml Defines the 'start_playback' action for the Boost.MSM state machine. This action is associated with transitions that initiate playback. The provided code is a placeholder with no specific implementation. ```cpp template<> struct Action { template void operator()(EVT const&, FSM&, SourceState&, TargetState&) { } }; ``` -------------------------------- ### State Machine Initialization and Event Processing Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/AnonymousTutorial This C++ snippet demonstrates the initialization of a state machine and processing an event. It shows how an event can trigger a transition back to the initial state, effectively starting a new cycle. This requires the Boost.MSM library. ```cpp p.start(); // this event will bring us back to the initial state and thus, a new "loop" will be started p.process_event(event1()); } } int main() { test(); return 0; } ``` -------------------------------- ### Test Connection State Machine Logic Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/ActivateStateBeforeTransitionEuml Provides a 'test' function that instantiates the 'Connection' state machine, starts it, processes 'connect' and 'disconnect' events, and then stops the machine. This demonstrates the flow and execution of the state machine. ```cpp #include #include #include // ... (previous definitions) ... namespace // Concrete FSM implementation { // ... (events, flags, actions, states, transition table, state machine declaration) ... void test() { Connection connection; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM connection.start(); // signal a connection connection.process_event(connect); // signal a disconnection connection.process_event(disconnect); connection.stop(); } } int main() { test(); return 0; } ``` -------------------------------- ### Test State Machine Transitions and Events (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SimpleWithFunctors Contains the main test logic for the state machine. It creates an instance of the 'player' state machine, starts it, and then processes various events ('open_close', 'cd_detected', 'pause', 'end_pause', 'stop') to demonstrate state transitions and actions. ```cpp void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); // go to Open, call on_exit on Empty, then action, then on_entry on Open p.process_event(open_close()); pstate(p); p.process_event(open_close()); pstate(p); // will be rejected, wrong disk type p.process_event( cd_detected("louie, louie",DISK_DVD)); pstate(p); p.process_event( cd_detected("louie, louie",DISK_CD)); pstate(p); // no need to call play() as the previous event does it in its action method //p.process_event(play()); // at this point, Play is active p.process_event(pause()); pstate(p); // go back to Playing p.process_event(end_pause()); pstate(p); p.process_event(pause()); pstate(p); p.process_event(stop()); pstate(p); // event leading to the same state // no action method called as it is not present in the transition table p.process_event(stop()); pstate(p); std::cout << "stop fsm" << std::endl; p.stop(); } ``` -------------------------------- ### C++ Main Function: Boost.MSM Player Test Execution Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/MsmComposite The main function demonstrates the usage of the Boost.MSM player state machine. It initializes the player, starts it, and then simulates a sequence of events within a loop, measuring the execution time on both Windows and POSIX systems. ```cpp int main() { // for timing #ifdef WIN32 LARGE_INTEGER res; ::QueryPerformanceFrequency(&res); LARGE_INTEGER li,li2; #else struct timeval tv1,tv2; gettimeofday(&tv1,NULL); #endif test_fsm::player p2; p2.start(); // for timing #ifdef WIN32 ::QueryPerformanceCounter(&li); #else gettimeofday(&tv1,NULL); #endif for (int i=0;i<100;++i) { p2.process_event(test_fsm::open_close()); p2.process_event(test_fsm::open_close()); p2.process_event(test_fsm::cd_detected()); p2.process_event(test_fsm::play()); for (int j=0;j<100;++j) { p2.process_event(test_fsm::NextSong()); p2.process_event(test_fsm::NextSong()); p2.process_event(test_fsm::PreviousSong()); p2.process_event(test_fsm::PreviousSong()); } p2.process_event(test_fsm::pause()); // go back to Playing p2.process_event(test_fsm::end_pause()); p2.process_event(test_fsm::pause()); p2.process_event(test_fsm::stop()); // event leading to the same state p2.process_event(test_fsm::stop()); p2.process_event(test_fsm::open_close()); p2.process_event(test_fsm::open_close()); } #ifdef WIN32 ::QueryPerformanceCounter(&li2); #else gettimeofday(&tv2,NULL); #endif #ifdef WIN32 std::cout << "msm took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" < " << state_names[p.current_state()[0]] << std::endl; } void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); // go to Open, call on_exit on Empty, then action, then on_entry on Open p.process_event(open_close); pstate(p); p.process_event(open_close); pstate(p); // will be rejected, wrong disk type p.process_event( cd_detected("louie, louie",DISK_DVD)); pstate(p); p.process_event( cd_detected("louie, louie",DISK_CD)); pstate(p); // no need to call play as the previous event does it in its action method //p.process_event(play); // at this point, Play is active p.process_event(pause); pstate(p); // go back to Playing p.process_event(end_pause); pstate(p); p.process_event(pause); pstate(p); p.process_event(stop); pstate(p); // event leading to the same state // no action method called as none is defined in the transition table p.process_event(stop); pstate(p); // test call to no_transition p.process_event(pause); pstate(p); } int main() { test(); return 0; } ``` -------------------------------- ### Search Functionality Test with Boost MSM State Machine Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/iPodSearch Test function demonstrating the complete search workflow, performing two searches with different query strings. It initializes the state machine, sets search parameters via state access, executes state transitions with start(), and iterates through results to display matching songs. ```cpp void test() { iPodSearch search; // look for "She Loves You" using the first letters search.get_state()->set_container("Sh");// will find 2 songs // needed to start the highest-level SM. This will call on_entry and mark the start of the SM search.start(); // display all the songs const iPodSearch::Songset& res = search.get_result(); for (iPodSearch::Songset::const_iterator it = res.begin();it != res.end();++it) { cout << "candidate song:" << *it << endl; } cout << "search using more letters" << endl; // look for "She Loves You" using more letters search.reset_search(); search.get_state()->set_container("She");// will find 1 song search.start(); const iPodSearch::Songset& res2 = search.get_result(); for (iPodSearch::Songset::const_iterator it = res2.begin();it != res2.end();++it) { cout << "candidate song:" << *it << endl; } } ``` -------------------------------- ### Player State Machine Definition and Initialization (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SM-2Arg Defines the player state machine using `msm::back::state_machine` and provides a utility function `pstate` to print the current state of the machine. The `test` function demonstrates starting the state machine and processing events, including a deferred event. ```cpp // back-end typedef msm::back::state_machine player; // // Testing utilities. // void pstate(player const& p) { static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode","SleepMode" }; for (unsigned int i=0;i " << state_names[p.current_state()[i]] << std::endl; } } void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); std::cout << "CDLoaded active:" << std::boolalpha << p.is_flag_active() << std::endl; //=> false (no CD yet) // test deferred event // deferred in Empty and Open, will be handled only after event cd_detected p.process_event(play()); // go to Open, call on_exit on Empty, then action, then on_entry on Open ``` -------------------------------- ### Test Function Demonstrating iPod FSM Event Processing Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/iPod_distributed/iPod Demonstrates practical usage of the iPod state machine by creating an instance, starting it, and processing a sequence of events including hold/release, button presses, and song navigation. Shows how events like Hold, SouthPressed, NoHold, PlayPause, and NextSong trigger state transitions and corresponding actions in the FSM. ```cpp void test() { iPod sm; sm.start(); // we first press Hold std::cout << "pressing hold" << std::endl; sm.process_event(Hold()); // pressing a button is now ignored std::cout << "pressing a button" << std::endl; sm.process_event(SouthPressed()); // or even one contained in a submachine sm.process_event(EastPressed()); // no more holding std::cout << "no more holding, end interrupt event sent" << std::endl; sm.process_event(NoHold()); std::cout << "pressing South button a short time" << std::endl; sm.process_event(SouthPressed()); // we suppose a short pressing leading to playing a song sm.process_event(SouthReleased()); // we move to the next song std::cout << "we move to the next song" << std::endl; sm.process_event(NextSong()); } ``` -------------------------------- ### Player State Machine Initialization and Event Processing (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/TestInternal Demonstrates the basic usage of the 'player' state machine. It includes starting the machine ('p.start()'), processing an event that is ignored ('p.process_event(to_ignore())'), and processing an event that causes a state transition ('p.process_event(open_close())'). The 'pstate(p)' function is called to show the state after each relevant event. ```C++ void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); // this event will be ignored and not call no_transition p.process_event(to_ignore()); // go to Open, call on_exit on Empty, then action, then on_entry on Open p.process_event(open_close()); pstate(p); ``` -------------------------------- ### Initialize and Start MSM State Machine Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/CompilerStressTestEuml Initializes the state machine by calling start(), which triggers on_entry actions and marks the beginning of state machine execution. This must be called before processing state transitions. ```cpp search.start(); ``` -------------------------------- ### Start and Stop a State Machine Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/ch03s06 Demonstrates how to start and stop an MSM state machine. The start() method activates the initial state and its entry behavior, useful for algorithms or repeated state machine runs. The stop() method triggers exit actions for current states. ```cpp my_fsm fsm; fsm.start(); // ... process events ... fsm.stop(); ``` -------------------------------- ### Implement 'Stopped' State and Transitions (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SCSimple Implements the 'Stopped' state, defining transitions for starting playback ('play' to 'Playing'), opening the drawer ('open_close' to 'Open'), and handling a 'stop' event to remain in the 'Stopped' state via the 'stopped_again' handler. This state manages the player when it is not actively playing media. ```cpp struct Stopped : sc::simple_state< Stopped, player > { Stopped() { /*std::cout << "entering Stopped" << std::endl;*/ } // entry ~Stopped() { /*std::cout << "leaving Stopped" << std::endl;*/ } // exit typedef mpl::list< sc::transition< play, Playing, player, &player::start_playback >, sc::transition< open_close, Open, player, &player::open_drawer >, sc::transition< stop, Stopped, player, &player::stopped_again > > reactions; }; ``` -------------------------------- ### Define Player State Machine Transition Table (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SimpleTutorial This C++ code defines the transition table for a player state machine using Boost.MPL vectors. It specifies the start state, event, next state, action, and optional guard for each transition. Dependencies include Boost.MPL. Inputs are events and current states; outputs are state changes and actions. Limitations might involve complex guards or actions not fully represented here. ```cpp struct transition_table : mpl::vector< // Start Event Next Action Guard // +---------+-------------+---------+---------------------+ ----------------------+ a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , open_close , Open , &p::open_drawer >, _row < Stopped , stop , Stopped >, // +---------+-------------+---------+---------------------+ ----------------------+ a_row < Open , open_close , Empty , &p::close_drawer >, // +---------+-------------+---------+---------------------+ ----------------------+ a_row < Empty , open_close , Open , &p::open_drawer >, row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >, row < Empty , cd_detected , Playing , &p::store_cd_info ,&p::auto_start >, // +---------+-------------+---------+---------------------+ ----------------------+ a_row < Playing , stop , Stopped , &p::stop_playback >, a_row < Playing , pause , Paused , &p::pause_playback >, a_row < Playing , open_close , Open , &p::stop_and_open >, // +---------+-------------+---------+---------------------+ ----------------------+ a_row < Paused , end_pause , Playing , &p::resume_playback >, a_row < Paused , stop , Stopped , &p::stop_playback >, a_row < Paused , open_close , Open , &p::stop_and_open > // +---------+-------------+---------+---------------------+ ----------------------+ > {}; ``` -------------------------------- ### Player State Machine Actions and Transition Table (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SM-2Arg Defines the actions executed during state transitions and the transition table for the player state machine. The transition table uses MPL vector and a_row to specify the start state, event, next state, action, and optional guard condition for each possible transition. Dependencies include the ``, ``, and `boost::msm` libraries. ```cpp //typedef Empty initial_state; // this is to have only one active state // transition actions void start_playback(play const&) { std::cout << "player::start_playback\n"; } void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; } void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; } void store_cd_info(cd_detected const&) { std::cout << "player::store_cd_info\n"; // generate another event to test the queue //process_event(play()); } void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; } void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; } void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; } void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; } void stopped_again(stop const&){std::cout << "player::stopped_again\n";} void start_sleep(go_sleep const&) { } void report_error(error_found const&) {std::cout << "player::report_error\n";} void report_end_error(end_error const&) {std::cout << "player::report_end_error\n";} // guard conditions typedef player_ p; // makes transition table cleaner // Transition table for player struct transition_table : mpl::vector< // Start Event Next Action Guard // +---------+-------------+---------+---------------------+----------------------+ a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , open_close , Open , &p::open_drawer >, a_row < Stopped , stop , Stopped , &p::stopped_again >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Open , open_close , Empty , &p::close_drawer >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Empty , open_close , Open , &p::open_drawer >, a_row < Empty , cd_detected , Stopped , &p::store_cd_info >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Playing , stop , Stopped , &p::stop_playback >, a_row < Playing , pause , Paused , &p::pause_playback >, a_row < Playing , open_close , Open , &p::stop_and_open >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Paused , end_pause , Playing , &p::resume_playback >, a_row < Paused , stop , Stopped , &p::stop_playback >, a_row < Paused , open_close , Open , &p::stop_and_open >, a_row < Paused , go_sleep ,SleepMode, &p::start_sleep >, // +---------+-------------+---------+---------------------+----------------------+ a_row < AllOk , error_found ,ErrorMode, &p::report_error >, a_row // +---------+-------------+---------+---------------------+----------------------+ > {}; // Replaces the default no-transition response. template void no_transition(Event const& e, FSM&,int state) { std::cout << "no transition from state " << state << " on event " << typeid(e).name() << std::endl; } ``` -------------------------------- ### State Entry/Exit Actions (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/Orthogonal-deferred Demonstrates the implementation of state entry and exit actions using template functions within state definitions. Examples include 'on_entry' and 'on_exit' methods for states like 'Song2', 'Song3', 'AllOk', and 'ErrorMode', which print messages to the console upon state transitions. ```cpp struct Song2 : public msm::front::state<> { template void on_entry(Event const&,FSM& ) {std::cout << "starting: Second song" << std::endl;} template void on_exit(Event const&,FSM& ) {std::cout << "finishing: Second Song" << std::endl;} }; struct Song3 : public msm::front::state<> { template void on_entry(Event const&,FSM& ) {std::cout << "starting: Third song" << std::endl;} template void on_exit(Event const&,FSM& ) {std::cout << "finishing: Third Song" << std::endl;} }; struct AllOk : public msm::front::state<> { template void on_entry(Event const&,FSM& ) {std::cout << "starting: AllOk" << std::endl;} template void on_exit(Event const&,FSM& ) {std::cout << "finishing: AllOk" << std::endl;} }; struct ErrorMode : //public msm::front::terminate_state<> // ErrorMode terminates the state machine public msm::front::interrupt_state*/ > // ErroMode just interrupts. Will resume if // the event end_error is generated { template void on_entry(Event const&,FSM& ) {std::cout << "starting: ErrorMode" << std::endl;} template void on_exit(Event const&,FSM& ) {std::cout << "finishing: ErrorMode" << std::endl;} }; ``` -------------------------------- ### Define Player State Machine with Transitions and Actions Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/History This C++ code defines the state machine for a player, including states like Stopped, Playing, Paused, and Open. It uses the Boost.MSM library to define a transition table that maps events to state changes and associated action functions. The `a_row` macro specifies the start state, event, next state, and the action to be executed. ```cpp struct player_ : msm::front::state_machine_def { // states struct Stopped : public msm::front::state<> { template void on_entry(Event const&,FSM& ) { std::cout << "entering: Stopped" << std::endl;} template void on_exit(Event const&,FSM& ) { std::cout << "leaving: Stopped" << std::endl;} }; struct Open : public msm::front::state<> { template void on_entry(Event const&,FSM& ) { std::cout << "entering: Open" << std::endl;} template void on_exit(Event const&,FSM& ) { std::cout << "leaving: Open" << std::endl;} }; struct Empty : public msm::front::state<> { template void on_entry(Event const&,FSM& ) { std::cout << "entering: Empty" << std::endl;} template void on_exit(Event const&,FSM& ) { std::cout << "leaving: Empty" << std::endl;} }; struct Playing_ : public msm::front::state<> { // Enables history typedef msm::back11::state_machine Playing; // enables Shallow History typedef msm::back11::state_machine< Playing_, msm::back11::state_machine, msm::back11::ShallowHistory > > Playing; // state not defining any entry or exit struct Paused : public msm::front::state<> { template void on_entry(Event const&,FSM& ) { std::cout << "entering: Paused" << std::endl;} template void on_exit(Event const&,FSM& ) { std::cout << "leaving: Paused" << std::endl;} }; // the initial state of the player SM. Must be defined typedef Empty initial_state; // transition actions void start_playback(play const&) { std::cout << "player::start_playback\n"; } void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; } void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; } void store_cd_info(cd_detected const& cd) {std::cout << "player::store_cd_info\n";} void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; } void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; } void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; } void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; } void stopped_again(stop const&){std::cout << "player::stopped_again\n";} // guard conditions typedef player_ p; // makes transition table cleaner // Transition table for player struct transition_table : mpl::vector< // Start Event Next Action Guard // +---------+-------------+---------+---------------------+----------------------+ a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , open_close , Open , &p::open_drawer >, a_row < Stopped , stop , Stopped , &p::stopped_again >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Open , open_close , Empty , &p::close_drawer >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Empty , open_close , Open , &p::open_drawer >, a_row < Empty , cd_detected , Stopped , &p::store_cd_info >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Playing , stop , Stopped , &p::stop_playback >, a_row < Playing , pause , Paused , &p::pause_playback >, a_row < Playing , open_close , Open , &p::stop_and_open >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Paused , end_pause , Playing , &p::resume_playback >, a_row < Paused , stop , Stopped , &p::stop_playback >, a_row < Paused , open_close , Open , &p::stop_and_open > // +---------+-------------+---------+---------------------+----------------------+ > {}; // Replaces the default no-transition response. template void no_transition(Event const& e, FSM&,int state) { std::cout << "no transition from state " << state << " on event " << typeid(e).name() << std::endl; } }; // Pick a back-end typedef msm::back11::state_machine player; }; ``` -------------------------------- ### Player State Machine Initialization Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/BoostCon09Full Demonstrates the initialization of the player state machine using `p.start()`. This function is necessary to begin the state machine's execution and trigger entry actions. ```cpp void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); std::cout << "CDLoaded active:" << std::boolalpha << p.is_flag_active() << std::endl; //=> false (no CD yet) // test deferred event } ``` -------------------------------- ### Player State Machine Actions Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/BoostCon09Full Defines member functions within the 'player_' class that are executed as actions during state transitions. These functions handle events like starting, stopping, pausing, and error reporting. ```cpp void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; } void end_playback (AllSongsPlayed const&) { std::cout << "player::end_playback\n"; } void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; } void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; } void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; } void stopped_again(stop const&){std::cout << "player::stopped_again\n";} void report_error(error_found const&) { std::cout << "player::report_error\n";} void report_end_error(end_error const&) { std::cout << "player::report_end_error\n";} ``` -------------------------------- ### iPodSearch State Machine Class Constructor and Initialization Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/iPodSearch Constructor initializes the iPodSearch state machine with predefined song data in the m_AllSongs container. It populates a song set with sample Beatles songs for testing purposes. This demonstrates the initialization pattern for FSM-based applications using Boost MSM. ```cpp iPodSearch_():m_AllSongs(),m_ResultSearch() { // add a few songs for testing m_AllSongs.insert("Let it be"); m_AllSongs.insert("Yellow submarine"); m_AllSongs.insert("Twist and Shout"); m_AllSongs.insert("She Loves You"); } ``` -------------------------------- ### Define Initial State and Transition Actions for Player SM in C++ Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/BoostCon09Full This C++ code defines the initial state for the player state machine as a combination of 'Empty' and 'AllOk'. It also declares transition actions: 'start_playback' for the 'play' event, 'open_drawer' and 'close_drawer' for the 'open_close' event, and 'store_cd_info' for the 'cd_detected' event, which includes a commented-out line to test event processing. ```cpp // the initial state of the player SM. Must be defined typedef mpl::vector initial_state; // transition actions void start_playback(play const&) { std::cout << "player::start_playback\n"; } void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; } void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; } void store_cd_info(cd_detected const&) { std::cout << "player::store_cd_info\n"; // generate another event to test the queue //cd.m_player.process_event(play()); } ``` -------------------------------- ### Simulate State Machine Event Processing (C++) Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/SimplePhoenix Contains the 'test' function which instantiates the 'player' state machine, starts it, and then processes various events like 'open_close', 'cd_detected', 'pause', and 'stop'. It uses 'pstate' to print the current state after each event. ```cpp void test() { player p; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM p.start(); // go to Open, call on_exit on Empty, then action, then on_entry on Open p.process_event(open_close); pstate(p); p.process_event(open_close); pstate(p); // will be rejected, wrong disk type p.process_event( cd_detected_event("louie, louie",DISK_DVD)); pstate(p); p.process_event( cd_detected_event("louie, louie",DISK_CD)); pstate(p); // no need to call play as the previous event does it in its action method //p.process_event(play); // at this point, Play is active p.process_event(pause); pstate(p); // go back to Playing p.process_event(end_pause); pstate(p); p.process_event(pause); pstate(p); p.process_event(stop); pstate(p); // event leading to the same state // no action method called as none is defined in the transition table p.process_event(stop); pstate(p); // test call to no_transition p.process_event(pause); pstate(p); } ``` -------------------------------- ### Player State Machine Transition Table Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/Serialize Defines the transitions for the player state machine. Each row specifies the start state, event, next state, and optional action and guard. The 'auto_start' guard handles potential transition conflicts. ```C++ struct transition_table : mpl::vector< // Start Event Next Action Guard // +---------+-------------+---------+---------------------+----------------------+ a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , open_close , Open , &p::open_drawer >, _row < Stopped , stop , Stopped >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Open , open_close , Empty , &p::close_drawer >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Empty , open_close , Open , &p::open_drawer >, row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >, row < Empty , cd_detected , Playing , &p::store_cd_info ,&p::auto_start >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Playing , stop , Stopped , &p::stop_playback >, a_row < Playing , pause , Paused , &p::pause_playback >, a_row < Playing , open_close , Open , &p::stop_and_open >, // +---------+-------------+---------+---------------------+----------------------+ a_row < Paused , end_pause , Playing , &p::resume_playback >, a_row < Paused , stop , Stopped , &p::stop_playback >, a_row < Paused , open_close , Open , &p::stop_and_open > // +---------+-------------+---------+---------------------+----------------------+ > {}; ``` -------------------------------- ### Create Player State Machine with Arguments in C++ Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/Constructor Demonstrates creating a player state machine instance. It shows how to pass arguments by reference (using boost::ref) and by value to the state machine's constructor, initializing its internal states and context. ```cpp void test() { SomeExternalContext ctx(3); // example 1 // create a player with an argument by reference and an int // (go to the constructor front-end) player p1(boost::ref(ctx),5); // example 2 // create a player with a copy of an Empty state, an argument by reference and an int // (last 2 go to the constructor front-end) player p2(msm::back::states_ << player_::Empty(1),boost::ref(ctx),5); std::cout << "Empty's data should be 1. Is: " << p2.get_state().data_ << std::endl; std::cout << "Set a new Empty state" p2.set_states(msm::back::states_ << player_::Empty(5)); std::cout << "Empty's data should be 5. Is: " << p2.get_state().data_ << std::endl; std::cout << "Set new Empty and Open states" p2.set_states(msm::back::states_ << player_::Empty(7) << player_::Open(2)); std::cout << "Empty's data should be 7. Is: " << p2.get_state().data_ << std::endl; std::cout << "Open's data should be 2. Is: " << p2.get_state().data_ << std::endl; // example 3 // create a player with a copy of an Empty state, a copy of a Playing submachine // (which is itself created by a copy of Song1) // an argument by reference and an int // (last 2 go to the constructor front-end) player p(msm::back::states_ << player_::Empty(1) << player_::Playing(msm::back::states_ << player_::Playing_::Song1(8)), boost::ref(ctx),5); std::cout << "Song1's data should be 8. Is: " << p.get_state().get_state().data_ << std::endl; } } int main() { test(); return 0; } ``` -------------------------------- ### Boost.MSM Menu Mode Transition Table Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/iPodEuml Specifies the transitions for the menu mode state machine. It manages states related to waiting for song choice, starting the current song, and exiting the menu. It includes initial states, attribute configurations, and flags. ```C++ // The list of MenuMode_ states BOOST_MSM_EUML_STATE(( WaitingForSongChoice_Entry ),WaitingForSongChoice) BOOST_MSM_EUML_STATE(( StartCurrentSong_Entry ),StartCurrentSong) BOOST_MSM_EUML_EXIT_STATE(( CloseMenu,MenuExit_Entry ),MenuExit) //stt BOOST_MSM_EUML_TRANSITION_TABLE(( // +------------------------------------------------------------------------------+ StartCurrentSong == WaitingForSongChoice + MenuMiddleButton , MenuExit == StartCurrentSong + SelectSong // +------------------------------------------------------------------------------+ ),menumode_transition_table ) BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (menumode_transition_table, //STT init_ << WaitingForSongChoice, // Init States no_action, // entry no_action, // exit attributes_ << no_attributes_, //attributes configure_<< MenuActive // Flags, Deferred events, configuration ),MenuMode_) typedef msm::back::state_machine MenuMode_type; MenuMode_type const MenuMode; ``` -------------------------------- ### Configure Main FSM Backend and State Configuration in Boost MSM Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/MsmComposite Sets up the main player state machine class that inherits from msm::front::state_machine_def with configuration options. Disables exception handling and message queuing for performance, and includes all primary states (Empty, Open, Stopped, Playing, Paused). ```cpp struct player_ : public msm::front::state_machine_def { typedef int no_exception_thrown; typedef int no_message_queue; struct Paused : public msm::front::state<> { template void on_entry(Event const&,FSM& ) {/*std::cout << "entering: Paused" << std::endl;*/} template void on_exit(Event const&,FSM& ) {/*std::cout << "leaving: Paused" << std::endl;*/} }; } ``` -------------------------------- ### Define MSM eUML Transition Table Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/examples/iPodEuml Defines the transition table for the state machine, specifying how the FSM moves between states based on events. It includes conditions and actions for transitions, such as starting a song, handling song completion, and managing play/pause functionality. ```cpp //stt BOOST_MSM_EUML_TRANSITION_TABLE(( // +------------------------------------------------------------------------------+ Paused == Playing + PlayPause , Paused == Playing + Off , Playing == Playing + StartSong / (if_then_(event_(m_Selected) > Int_<0>() && event_(m_Selected) < fsm_(m_NumberOfSongs), fsm_(m_SongIndex) = event_(m_Selected) ),show_selected_song) , Playing == Playing + SongFinished / (if_then_else_(++fsm_(m_SongIndex) <= fsm_(m_NumberOfSongs), /*if*/ show_playing_song, /*then*/ (fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay))/*else*/ ) ) , Playing == Paused + PlayPause , Playing == Paused + StartSong )) ``` -------------------------------- ### Select MSM State Machine Backend Source: https://www.boost.org/doc/libs/latest/libs/msm/doc/HTML/ch03s02 Selects the backend for the MSM state machine. `msm::back11::state_machine` is the current backend, templated with the state machine definition. This creates a ready-to-use state machine. ```cpp typedef msm::back11::state_machine player; ```