1 // Copyright 2010 Christophe Henry 2 // henry UNDERSCORE christophe AT hotmail DOT com 3 // This is an extended version of the state machine available in the boost::mpl library 4 // Distributed under the same license as the original. 5 // Copyright for the original version: 6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed 7 // under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 11 #include <iostream> 12 13 #include <boost/msm/back/state_machine.hpp> 14 #include <boost/msm/front/state_machine_def.hpp> 15 #include <boost/msm/front/euml/euml.hpp> 16 17 using namespace std; 18 namespace msm = boost::msm; 19 namespace mpl = boost::mpl; 20 using namespace boost::msm::front::euml; 21 22 23 namespace // Concrete FSM implementation 24 { 25 // events 26 BOOST_MSM_EUML_EVENT(connect) BOOST_MSM_EUML_EVENT(disconnect)27 BOOST_MSM_EUML_EVENT(disconnect) 28 29 // flag 30 BOOST_MSM_EUML_FLAG(is_connected) 31 32 BOOST_MSM_EUML_ACTION(SignalConnect) 33 { 34 template <class FSM,class EVT,class SourceState,class TargetState> 35 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 36 { 37 // by default, this would be wrong (shows false) 38 cout << "SignalConnect. Connected? " 39 << std::boolalpha 40 << fsm.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(is_connected)>() << endl; 41 } 42 }; BOOST_MSM_EUML_ACTION(SignalDisconnect)43 BOOST_MSM_EUML_ACTION(SignalDisconnect) 44 { 45 template <class FSM,class EVT,class SourceState,class TargetState> 46 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 47 { 48 // by default, this would be wrong (shows true) 49 cout << "SignalDisconnect. Connected? " 50 << std::boolalpha 51 << fsm.template is_flag_active<BOOST_MSM_EUML_FLAG_NAME(is_connected)>() 52 << endl; 53 } 54 }; 55 56 // The list of FSM states BOOST_MSM_EUML_ACTION(Connected_Entry)57 BOOST_MSM_EUML_ACTION(Connected_Entry) 58 { 59 template <class Event,class FSM,class STATE> 60 void operator()(Event const&,FSM&,STATE& ) 61 { 62 std::cout << "entering: Connected" << std::endl; 63 } 64 }; BOOST_MSM_EUML_ACTION(Connected_Exit)65 BOOST_MSM_EUML_ACTION(Connected_Exit) 66 { 67 template <class Event,class FSM,class STATE> 68 void operator()(Event const&,FSM&,STATE& ) 69 { 70 std::cout << "leaving: Connected" << std::endl; 71 } 72 }; 73 BOOST_MSM_EUML_STATE(( Connected_Entry,Connected_Exit, 74 attributes_ << no_attributes_, 75 configure_<< is_connected ),Connected) 76 BOOST_MSM_EUML_ACTION(Disconnected_Entry)77 BOOST_MSM_EUML_ACTION(Disconnected_Entry) 78 { 79 template <class Event,class FSM,class STATE> 80 void operator()(Event const&,FSM&,STATE& ) 81 { 82 std::cout << "entering: Disconnected" << std::endl; 83 } 84 }; BOOST_MSM_EUML_ACTION(Disconnected_Exit)85 BOOST_MSM_EUML_ACTION(Disconnected_Exit) 86 { 87 template <class Event,class FSM,class STATE> 88 void operator()(Event const&,FSM&,STATE& ) 89 { 90 std::cout << "leaving: Disconnected" << std::endl; 91 } 92 }; 93 BOOST_MSM_EUML_STATE(( Disconnected_Entry,Disconnected_Exit ),Disconnected) 94 95 // replaces the old transition table 96 BOOST_MSM_EUML_TRANSITION_TABLE(( 97 Disconnected == Connected + disconnect / SignalDisconnect , 98 Connected == Disconnected + connect / SignalConnect 99 // +------------------------------------------------------------------------------+ 100 ),transition_table) 101 BOOST_MSM_EUML_ACTION(Log_No_Transition)102 BOOST_MSM_EUML_ACTION(Log_No_Transition) 103 { 104 template <class FSM,class Event> 105 void operator()(Event const& e,FSM&,int state) 106 { 107 std::cout << "no transition from state " << state 108 << " on event " << typeid(e).name() << std::endl; 109 } 110 }; 111 112 // create a state machine "on the fly" 113 BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT 114 init_ << Disconnected, // Init State 115 no_action, // Entry 116 no_action, // Exit 117 attributes_ << no_attributes_, // Attributes 118 configure_ << switch_active_before_transition, // configuration 119 Log_No_Transition // no_transition handler 120 ), 121 Connection_) //fsm name 122 123 typedef msm::back::state_machine<Connection_> Connection; 124 test()125 void test() 126 { 127 Connection connection; 128 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM 129 connection.start(); 130 // signal a connection 131 connection.process_event(connect); 132 // signal a disconnection 133 connection.process_event(disconnect); 134 connection.stop(); 135 } 136 } 137 main()138 int main() 139 { 140 test(); 141 return 0; 142 } 143 144 145