]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/HTML/examples/SimpleTutorialWithEumlTableTypeErasure.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / msm / doc / HTML / examples / SimpleTutorialWithEumlTableTypeErasure.cpp
1 #include <iostream>
2 // back-end
3 #include <boost/msm/back/state_machine.hpp>
4 //front-end
5 #include <boost/msm/front/state_machine_def.hpp>
6 #include <boost/msm/front/euml/euml.hpp>
7 #include <boost/msm/event_traits.hpp>
8
9 #include <boost/type_erasure/any.hpp>
10 #include <boost/type_erasure/member.hpp>
11 #include <boost/type_erasure/builtin.hpp>
12 #include <boost/type_erasure/constructible.hpp>
13 #include <boost/type_erasure/relaxed_match.hpp>
14 #include <boost/type_erasure/any_cast.hpp>
15
16 namespace msm = boost::msm;
17 namespace mpl = boost::mpl;
18 using namespace std;
19 using namespace msm::front::euml;
20
21 // entry/exit/action/guard logging functors
22 #include "logging_functors.h"
23
24 BOOST_TYPE_ERASURE_MEMBER((has_getNumber), getNumber, 0);
25 //type erasure event
26 typedef ::boost::mpl::vector<
27 has_getNumber<int(), const boost::type_erasure::_self>,
28 boost::type_erasure::relaxed_match,
29 boost::type_erasure::copy_constructible<>,
30 boost::type_erasure::typeid_<>
31 > any_number_event_concept;
32 struct any_number_event : boost::type_erasure::any<any_number_event_concept>,
33 msm::front::euml::euml_event<any_number_event>
34 {
35 template <class U>
36 any_number_event(U const& u): boost::type_erasure::any<any_number_event_concept> (u){}
37 any_number_event(): boost::type_erasure::any<any_number_event_concept> (){}
38 };
39
40
41 namespace boost { namespace msm{
42 template<>
43 struct is_kleene_event< any_number_event >
44 {
45 typedef boost::mpl::true_ type;
46 };
47 }}
48
49 namespace
50 {
51 // events
52 struct play_impl : msm::front::euml::euml_event<play_impl> {int getNumber()const {return 0;}};
53 struct end_pause_impl : msm::front::euml::euml_event<end_pause_impl>{int getNumber()const {return 1;}};
54 struct stop_impl : msm::front::euml::euml_event<stop_impl>{int getNumber()const {return 2;}};
55 struct pause_impl : msm::front::euml::euml_event<pause_impl>{int getNumber()const {return 3;}};
56 struct open_close_impl : msm::front::euml::euml_event<open_close_impl>{int getNumber()const {return 4;}};
57 struct cd_detected_impl : msm::front::euml::euml_event<cd_detected_impl>{int getNumber()const {return 5;}};
58
59 // define some dummy instances for use in the transition table
60 // it is also possible to default-construct them instead:
61 // struct play {};
62 // inside the table: play()
63 play_impl play;
64 end_pause_impl end_pause;
65 stop_impl stop;
66 pause_impl pause;
67 open_close_impl open_close;
68 cd_detected_impl cd_detected;
69 any_number_event number_event;
70
71 // The list of FSM states
72 // they have to be declared outside of the front-end only to make VC happy :(
73 // note: gcc would have no problem
74 struct Empty_impl : public msm::front::state<> , public msm::front::euml::euml_state<Empty_impl>
75 {
76 // every (optional) entry/exit methods get the event passed.
77 template <class Event,class FSM>
78 void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
79 template <class Event,class FSM>
80 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
81 };
82 struct Open_impl : public msm::front::state<> , public msm::front::euml::euml_state<Open_impl>
83 {
84 template <class Event,class FSM>
85 void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
86 template <class Event,class FSM>
87 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
88 };
89
90 struct Stopped_impl : public msm::front::state<> , public msm::front::euml::euml_state<Stopped_impl>
91 {
92 template <class Event,class FSM>
93 void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
94 template <class Event,class FSM>
95 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
96 };
97
98 struct Playing_impl : public msm::front::state<> , public msm::front::euml::euml_state<Playing_impl>
99 {
100 template <class Event,class FSM>
101 void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
102 template <class Event,class FSM>
103 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
104 };
105
106 // state not defining any entry or exit
107 struct Paused_impl : public msm::front::state<> , public msm::front::euml::euml_state<Paused_impl>
108 {
109 };
110 //to make the transition table more readable
111 Empty_impl const Empty;
112 Open_impl const Open;
113 Stopped_impl const Stopped;
114 Playing_impl const Playing;
115 Paused_impl const Paused;
116
117 BOOST_MSM_EUML_ACTION(pause_playback2)
118 {
119 template <class FSM,class EVT,class SourceState,class TargetState>
120 void operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
121 {
122 cout << "player::pause_playback2" << endl;
123 std::cout << "event type: " << typeid(EVT).name() << std::endl;
124 std::cout << "event's number: " << evt.getNumber() << std::endl;
125 }
126 };
127 // front-end: define the FSM structure
128 struct player_ : public msm::front::state_machine_def<player_>
129 {
130
131 // the initial state of the player SM. Must be defined
132 typedef Empty_impl initial_state;
133
134 // Transition table for player
135 // replaces the old transition table
136 BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
137 Stopped + play / start_playback == Playing ,
138 Stopped + open_close / open_drawer == Open ,
139 Stopped + stop == Stopped ,
140 // +------------------------------------------------------------------------------+
141 Open + open_close / close_drawer == Empty ,
142 // +------------------------------------------------------------------------------+
143 Empty + open_close / open_drawer == Open ,
144 Empty + cd_detected /(store_cd_info,
145 msm::front::euml::process_(play)) == Stopped ,
146 // +------------------------------------------------------------------------------+
147 Playing + stop / stop_playback == Stopped ,
148 Playing + number_event / pause_playback == Paused ,
149 Playing + open_close / stop_and_open == Open ,
150 // +------------------------------------------------------------------------------+
151 Paused + end_pause / resume_playback == Playing ,
152 Paused + stop / stop_playback == Stopped ,
153 Paused + open_close / stop_and_open == Open
154 // +------------------------------------------------------------------------------+
155 ),transition_table)
156
157 // Replaces the default no-transition response.
158 template <class FSM,class Event>
159 void no_transition(Event const& e, FSM&,int state)
160 {
161 std::cout << "no transition from state " << state
162 << " on event " << typeid(e).name() << std::endl;
163 }
164 };
165 // Pick a back-end
166 typedef msm::back::state_machine<player_> player;
167
168 //
169 // Testing utilities.
170 //
171 static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
172 void pstate(player const& p)
173 {
174 std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
175 }
176
177 void test()
178 {
179 player p;
180 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
181 p.start();
182 // go to Open, call on_exit on Empty, then action, then on_entry on Open
183 p.process_event(open_close); pstate(p);
184 p.process_event(open_close); pstate(p);
185 p.process_event(cd_detected); pstate(p);
186
187 // at this point, Play is active
188 p.process_event(pause); pstate(p);
189 // go back to Playing
190 p.process_event(end_pause); pstate(p);
191 p.process_event(pause); pstate(p);
192 p.process_event(stop); pstate(p);
193 // event leading to the same state
194 // no action method called as it is not present in the transition table
195 p.process_event(stop); pstate(p);
196 }
197 }
198
199 int main()
200 {
201 test();
202
203
204 return 0;
205 }