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>
any_number_eventany_number_event36     any_number_event(U const& u): boost::type_erasure::any<any_number_event_concept> (u){}
any_number_eventany_number_event37     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
getNumber__anoncf2bbc220111::play_impl52     struct play_impl : msm::front::euml::euml_event<play_impl> {int getNumber()const {return 0;}};
getNumber__anoncf2bbc220111::end_pause_impl53     struct end_pause_impl : msm::front::euml::euml_event<end_pause_impl>{int getNumber()const {return 1;}};
getNumber__anoncf2bbc220111::stop_impl54     struct stop_impl : msm::front::euml::euml_event<stop_impl>{int getNumber()const {return 2;}};
getNumber__anoncf2bbc220111::pause_impl55     struct pause_impl : msm::front::euml::euml_event<pause_impl>{int getNumber()const {return 3;}};
getNumber__anoncf2bbc220111::open_close_impl56     struct open_close_impl : msm::front::euml::euml_event<open_close_impl>{int getNumber()const {return 4;}};
getNumber__anoncf2bbc220111::cd_detected_impl57     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>
on_entry__anoncf2bbc220111::Empty_impl78         void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
79         template <class Event,class FSM>
on_exit__anoncf2bbc220111::Empty_impl80         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>
on_entry__anoncf2bbc220111::Open_impl85         void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
86         template <class Event,class FSM>
on_exit__anoncf2bbc220111::Open_impl87         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>
on_entry__anoncf2bbc220111::Stopped_impl93         void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
94         template <class Event,class FSM>
on_exit__anoncf2bbc220111::Stopped_impl95         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>
on_entry__anoncf2bbc220111::Playing_impl101         void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
102         template <class Event,class FSM>
on_exit__anoncf2bbc220111::Playing_impl103         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 
BOOST_MSM_EUML_ACTION(pause_playback2)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>
no_transition__anoncf2bbc220111::player_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" };
pstate(player const & p)172     void pstate(player const& p)
173     {
174         std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
175     }
176 
test()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 
main()199 int main()
200 {
201     test();
202 
203 
204     return 0;
205 }
206