3 #include <boost/msm/back/state_machine.hpp>
5 #include <boost/msm/front/state_machine_def.hpp>
6 #include <boost/msm/front/euml/euml.hpp>
7 #include <boost/msm/event_traits.hpp>
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>
16 namespace msm
= boost::msm
;
17 namespace mpl
= boost::mpl
;
19 using namespace msm::front::euml
;
21 // entry/exit/action/guard logging functors
22 #include "logging_functors.h"
24 BOOST_TYPE_ERASURE_MEMBER((has_getNumber
), getNumber
, 0);
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
>
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
> (){}
41 namespace boost
{ namespace msm
{
43 struct is_kleene_event
< any_number_event
>
45 typedef boost::mpl::true_ type
;
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;}};
59 // define some dummy instances for use in the transition table
60 // it is also possible to default-construct them instead:
62 // inside the table: play()
64 end_pause_impl end_pause
;
67 open_close_impl open_close
;
68 cd_detected_impl cd_detected
;
69 any_number_event number_event
;
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
>
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
;}
82 struct Open_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Open_impl
>
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
;}
90 struct Stopped_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Stopped_impl
>
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
;}
98 struct Playing_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Playing_impl
>
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
;}
106 // state not defining any entry or exit
107 struct Paused_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Paused_impl
>
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
;
117 BOOST_MSM_EUML_ACTION(pause_playback2
)
119 template <class FSM
,class EVT
,class SourceState
,class TargetState
>
120 void operator()(EVT
const& evt
,FSM
&,SourceState
& ,TargetState
& )
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
;
127 // front-end: define the FSM structure
128 struct player_
: public msm::front::state_machine_def
<player_
>
131 // the initial state of the player SM. Must be defined
132 typedef Empty_impl initial_state
;
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 // +------------------------------------------------------------------------------+
157 // Replaces the default no-transition response.
158 template <class FSM
,class Event
>
159 void no_transition(Event
const& e
, FSM
&,int state
)
161 std::cout
<< "no transition from state " << state
162 << " on event " << typeid(e
).name() << std::endl
;
166 typedef msm::back::state_machine
<player_
> player
;
169 // Testing utilities.
171 static char const* const state_names
[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
172 void pstate(player
const& p
)
174 std::cout
<< " -> " << state_names
[p
.current_state()[0]] << std::endl
;
180 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
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
);
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
);