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