]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | // same as iPodSearch.cpp but using eUML | |
12 | // requires boost >= v1.40 because using mpl::string | |
13 | ||
14 | #include <vector> | |
15 | #include <iostream> | |
16 | ||
17 | #include <boost/msm/back/state_machine.hpp> | |
18 | #include <boost/msm/front/euml/euml.hpp> | |
19 | #include <boost/msm/front/euml/stl.hpp> | |
20 | ||
21 | using namespace std; | |
22 | using namespace boost::msm::front::euml; | |
23 | namespace msm = boost::msm; | |
24 | namespace mpl = boost::mpl; | |
25 | ||
26 | // how long the timer will ring when countdown elapsed. | |
27 | #define RINGING_TIME 5 | |
28 | ||
29 | namespace // Concrete FSM implementation | |
30 | { | |
31 | // events | |
32 | BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song) | |
33 | BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), OneSongDef) | |
34 | struct OneSong_impl : euml_event<OneSong_impl>,OneSongDef | |
35 | { | |
36 | OneSong_impl(){} | |
37 | OneSong_impl(const string& asong) | |
38 | { | |
39 | get_attribute(m_song)=asong; | |
40 | } | |
41 | OneSong_impl(const char* asong) | |
42 | { | |
43 | get_attribute(m_song)=asong; | |
44 | } | |
45 | OneSong_impl(const OneSong_impl& asong) | |
46 | { | |
47 | get_attribute(m_song)=asong.get_attribute(m_song); | |
48 | } | |
49 | const string& get_data() const {return get_attribute(m_song);} | |
50 | }; | |
51 | OneSong_impl const OneSong; | |
52 | ||
53 | // attribute definitions | |
54 | BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>,m_src_container) | |
55 | BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>,m_tgt_container) | |
56 | BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_letters) | |
57 | BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>::iterator,m_src_it) | |
58 | ||
59 | // the same attribute name can be reused | |
60 | BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), NotFoundDef) | |
61 | BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(NotFound,NotFoundDef) | |
62 | ||
63 | BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef) | |
64 | BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(Found,FoundDef) | |
65 | ||
66 | BOOST_MSM_EUML_EVENT(Done) | |
67 | ||
68 | // Concrete FSM implementation | |
69 | ||
70 | // The list of FSM states | |
71 | BOOST_MSM_EUML_STATE(( (push_back_(fsm_(m_tgt_container),event_(m_song)) | |
72 | ,process_(Done)), | |
73 | no_action ),Insert) | |
74 | ||
75 | BOOST_MSM_EUML_STATE(( if_then_else_( string_find_(event_(m_song),state_(m_letters)) != Npos_<string>() , | |
76 | process2_(Found,event_(m_song)), | |
77 | process2_(NotFound,event_(m_song)) ) , | |
78 | no_action, | |
79 | attributes_ << m_letters ),StringFind) | |
80 | ||
81 | BOOST_MSM_EUML_STATE(( if_then_( state_(m_src_it) != end_(fsm_(m_src_container)), | |
82 | process2_(OneSong,*(state_(m_src_it)++)) ), | |
83 | no_action, | |
84 | attributes_ << m_src_it ),Foreach) | |
85 | ||
86 | // replaces the old transition table | |
87 | BOOST_MSM_EUML_TRANSITION_TABLE(( | |
88 | StringFind == Foreach + OneSong , | |
89 | Insert == StringFind + Found , | |
90 | Foreach == StringFind + NotFound , | |
91 | Foreach == Insert + Done | |
92 | // +------------------------------------------------------------------------------+ | |
93 | ),transition_table ) | |
94 | ||
95 | BOOST_MSM_EUML_ACTION(Log_No_Transition) | |
96 | { | |
97 | template <class FSM,class Event> | |
98 | void operator()(Event const& e,FSM&,int state) | |
99 | { | |
100 | std::cout << "no transition from state " << state | |
101 | << " on event " << typeid(e).name() << std::endl; | |
102 | } | |
103 | }; | |
104 | // create a state machine "on the fly" | |
105 | BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT | |
106 | init_ << Foreach, // Init | |
107 | ( | |
108 | clear_(fsm_(m_src_container)), //clear source | |
109 | clear_(fsm_(m_tgt_container)), //clear results | |
110 | push_back_(fsm_(m_src_container), | |
111 | String_<mpl::string<'Let ','it ','be'> >()),//add a song | |
112 | push_back_(fsm_(m_src_container), | |
113 | String_<mpl::string<'Yell','ow s','ubma','rine'> >()),//add a song | |
114 | push_back_(fsm_(m_src_container), | |
115 | String_<mpl::string<'Twis','t an','d Sh','out'> >()),//add a song | |
116 | push_back_(fsm_(m_src_container), | |
117 | String_<mpl::string<'She ','love','s yo','u'> >()),//add a song | |
118 | attribute_(substate_(Foreach()),m_src_it) | |
119 | = begin_(fsm_(m_src_container)) //set the search begin | |
120 | ), // Entry | |
121 | no_action, // Exit | |
122 | attributes_ << m_src_container // song list | |
123 | << m_tgt_container, // result | |
124 | configure_<< no_configure_, | |
125 | Log_No_Transition | |
126 | ), | |
127 | iPodSearch_) //fsm name | |
128 | ||
129 | ||
130 | // choice of back-end | |
131 | typedef msm::back::state_machine<iPodSearch_> iPodSearch; | |
132 | ||
133 | void test() | |
134 | { | |
135 | iPodSearch search; | |
136 | ||
137 | // look for "She Loves You" using the first letters | |
138 | search.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="Sh";// will find 2 songs | |
139 | ||
140 | // needed to start the highest-level SM. This will call on_entry and mark the start of the SM | |
141 | search.start(); | |
142 | // display all the songs | |
143 | for (vector<OneSong_impl>::const_iterator it = search.get_attribute(m_tgt_container).begin(); | |
144 | it != search.get_attribute(m_tgt_container).end();++it) | |
145 | { | |
146 | cout << "candidate song:" << (*it).get_attribute(m_song) << endl; | |
147 | } | |
148 | ||
149 | cout << "search using more letters" << endl; | |
150 | // look for "She Loves You" using more letters | |
151 | search.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="She";// will find 1 song | |
152 | search.start(); | |
153 | // display all the songs | |
154 | for (vector<OneSong_impl>::const_iterator it = search.get_attribute(m_tgt_container).begin(); | |
155 | it != search.get_attribute(m_tgt_container).end();++it) | |
156 | { | |
157 | cout << "candidate song:" << (*it).get_attribute(m_song) << endl; | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
162 | int main() | |
163 | { | |
164 | test(); | |
165 | return 0; | |
166 | } |