]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/doc/PDF/examples/ParsingDigits.cpp
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)
11 #define FUSION_MAX_VECTOR_SIZE 20
13 #include <boost/msm/back/state_machine.hpp>
14 #include "char_event_dispatcher.hpp"
15 #include <boost/msm/front/state_machine_def.hpp>
16 #include <boost/msm/front/functor_row.hpp>
17 #include <boost/timer.hpp>
19 namespace msm
= boost::msm
;
20 namespace mpl
= boost::mpl
;
21 using namespace msm::front
;
31 struct end_sub
{template <class Event
> end_sub(Event
const&){}};
33 struct default_char
{};
37 namespace test_fsm
// Concrete FSM implementation
39 // Concrete FSM implementation
40 struct parsing_
: public msm::front::state_machine_def
<parsing_
>
42 // no need for exception handling or message queue
43 typedef int no_exception_thrown
;
44 typedef int no_message_queue
;
46 struct Waiting
: public msm::front::state
<>
48 // optional entry/exit methods
49 //template <class Event,class FSM>
50 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Waiting" << std::endl;}
51 //template <class Event,class FSM>
52 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Waiting" << std::endl;}
54 struct Digit1
: public msm::front::state
<>
56 // optional entry/exit methods
57 //template <class Event,class FSM>
58 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit1" << std::endl;}
59 //template <class Event,class FSM>
60 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit1" << std::endl;}
62 struct Digit2
: public msm::front::state
<>
64 // optional entry/exit methods
65 //template <class Event,class FSM>
66 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit2" << std::endl;}
67 //template <class Event,class FSM>
68 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit2" << std::endl;}
70 struct Digit3
: public msm::front::state
<>
72 // optional entry/exit methods
73 //template <class Event,class FSM>
74 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit3" << std::endl;}
75 //template <class Event,class FSM>
76 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit3" << std::endl;}
78 struct Digit4
: public msm::front::state
<>
80 // optional entry/exit methods
81 //template <class Event,class FSM>
82 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit4" << std::endl;}
83 //template <class Event,class FSM>
84 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit4" << std::endl;}
86 struct MinusChar1
: public msm::front::state
<>
88 // optional entry/exit methods
89 //template <class Event,class FSM>
90 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar1" << std::endl;}
91 //template <class Event,class FSM>
92 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar1" << std::endl;}
94 struct Digit5
: public msm::front::state
<>
96 // optional entry/exit methods
97 //template <class Event,class FSM>
98 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit5" << std::endl;}
99 //template <class Event,class FSM>
100 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit5" << std::endl;}
102 struct Digit6
: public msm::front::state
<>
104 // optional entry/exit methods
105 //template <class Event,class FSM>
106 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit6" << std::endl;}
107 //template <class Event,class FSM>
108 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit6" << std::endl;}
110 struct Digit7
: public msm::front::state
<>
112 // optional entry/exit methods
113 //template <class Event,class FSM>
114 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit7" << std::endl;}
115 //template <class Event,class FSM>
116 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit7" << std::endl;}
118 struct Digit8
: public msm::front::state
<>
120 // optional entry/exit methods
121 //template <class Event,class FSM>
122 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit8" << std::endl;}
123 //template <class Event,class FSM>
124 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit8" << std::endl;}
126 struct MinusChar2
: public msm::front::state
<>
128 // optional entry/exit methods
129 //template <class Event,class FSM>
130 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar2" << std::endl;}
131 //template <class Event,class FSM>
132 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar2" << std::endl;}
134 struct Digit9
: public msm::front::state
<>
136 // optional entry/exit methods
137 //template <class Event,class FSM>
138 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit9" << std::endl;}
139 //template <class Event,class FSM>
140 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit9" << std::endl;}
142 struct Digit10
: public msm::front::state
<>
144 // optional entry/exit methods
145 //template <class Event,class FSM>
146 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit10" << std::endl;}
147 //template <class Event,class FSM>
148 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit10" << std::endl;}
150 struct Digit11
: public msm::front::state
<>
152 // optional entry/exit methods
153 //template <class Event,class FSM>
154 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit11" << std::endl;}
155 //template <class Event,class FSM>
156 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit11" << std::endl;}
158 struct Digit12
: public msm::front::state
<>
160 // optional entry/exit methods
161 //template <class Event,class FSM>
162 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit12" << std::endl;}
163 //template <class Event,class FSM>
164 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit12" << std::endl;}
166 struct MinusChar3
: public msm::front::state
<>
168 // optional entry/exit methods
169 //template <class Event,class FSM>
170 //void on_entry(Event const&,FSM& ) {std::cout << "entering: MinusChar3" << std::endl;}
171 //template <class Event,class FSM>
172 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: MinusChar3" << std::endl;}
174 struct Digit13
: public msm::front::state
<>
176 // optional entry/exit methods
177 //template <class Event,class FSM>
178 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit13" << std::endl;}
179 //template <class Event,class FSM>
180 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit13" << std::endl;}
182 struct Digit14
: public msm::front::state
<>
184 // optional entry/exit methods
185 //template <class Event,class FSM>
186 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit14" << std::endl;}
187 //template <class Event,class FSM>
188 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit14" << std::endl;}
190 struct Digit15
: public msm::front::state
<>
192 // optional entry/exit methods
193 //template <class Event,class FSM>
194 //void on_entry(Event const&,FSM& ) {std::cout << "entering: Digit15" << std::endl;}
195 //template <class Event,class FSM>
196 //void on_exit(Event const&,FSM& ) {std::cout << "leaving: Digit15" << std::endl;}
198 //struct Start : public msm::front::state<> {};
199 struct Parsed
: public msm::front::state
<> {};
200 //struct Failed : public msm::front::state<> {};
202 // the initial state of the player SM. Must be defined
203 typedef Waiting initial_state
;
204 // transition actions
207 template <class FSM
,class EVT
,class SourceState
,class TargetState
>
208 void operator()(EVT
const& ,FSM
&,SourceState
& ,TargetState
& )
210 std::cout
<< "Parsed!" << std::endl
;
217 // Transition table for parsing_
218 struct transition_table
: mpl::vector
<
219 // Start Event Next Action Guard
220 // +-------------+-------------------+---------+---------------------+----------------------+
221 Row
< Waiting
, digit
, Digit1
>,
222 Row
< Digit1
, digit
, Digit2
>,
223 Row
< Digit2
, digit
, Digit3
>,
224 Row
< Digit3
, digit
, Digit4
>,
225 Row
< Digit4
, event_char
<'-'> , MinusChar1
>,
226 Row
< MinusChar1
, digit
, Digit5
>,
227 Row
< Digit5
, digit
, Digit6
>,
228 Row
< Digit6
, digit
, Digit7
>,
229 Row
< Digit7
, digit
, Digit8
>,
230 Row
< Digit8
, event_char
<'-'> , MinusChar2
>,
231 Row
< MinusChar2
, digit
, Digit9
>,
232 Row
< Digit9
, digit
, Digit10
>,
233 Row
< Digit10
, digit
, Digit11
>,
234 Row
< Digit11
, digit
, Digit12
>,
235 Row
< Digit12
, event_char
<'-'> , MinusChar3
>,
236 Row
< MinusChar3
, digit
, Digit13
>,
237 Row
< Digit13
, digit
, Digit14
>,
238 Row
< Digit14
, digit
, Digit15
>,
239 Row
< Digit15
, eos
, Parsed
>,
240 Row
< Parsed
, eos
, Waiting
>
241 // +---------+-------------+---------+---------------------+----------------------+
245 // Replaces the default no-transition response.
246 template <class FSM
,class Event
>
247 void no_transition(Event
const& e
, FSM
&,int state
)
249 std::cout
<< "no transition from state " << state
250 << " on event " << typeid(e
).name() << std::endl
;
253 typedef msm::back::state_machine
<parsing_
> parsing
;
257 long mtime(struct timeval
& tv1
,struct timeval
& tv2
)
259 return (tv2
.tv_sec
-tv1
.tv_sec
) *1000000 + ((tv2
.tv_usec
-tv1
.tv_usec
));
263 // This declares the statically-initialized char_event_dispatcher instance.
265 const msm::back::char_event_dispatcher
<Fsm
>
266 msm::back::char_event_dispatcher
<Fsm
>::instance
;
270 Parser():p(){p
.start();}
271 void new_char(char c
)
273 typedef msm::back::char_event_dispatcher
<test_fsm::parsing
> table
;
274 table::instance
.process_event(p
,c
);
276 void finish_string(){p
.process_event(eos());}
277 void reinit(){p
.process_event(eos());}
281 void msm_match(const char* input
)
288 //for (size_t j=0;j<len;++j)
293 p
.process_event(char_0());
296 p
.process_event(char_1());
299 p
.process_event(char_2());
302 p
.process_event(char_3());
305 p
.process_event(char_4());
308 p
.process_event(char_5());
311 p
.process_event(char_6());
314 p
.process_event(char_7());
317 p
.process_event(char_8());
320 p
.process_event(char_9());
323 p
.process_event(event_char
<'-'>());
326 p
.process_event(default_char());
331 p
.process_event(eos());
332 p
.process_event(eos());
335 double time_match(const char* text
)
339 int counter
, repeats
;
345 for(counter
= 0; counter
< iter
; ++counter
)
349 result
= tim
.elapsed();
351 } while(result
< 0.5);
354 // repeat test and report least value for consistency:
355 for(repeats
= 0; repeats
< 10; ++repeats
)
358 for(counter
= 0; counter
< iter
; ++counter
)
363 result
= (std::min
)(run
, result
);
365 return result
/ iter
;
372 ::QueryPerformanceFrequency(&res
);
373 LARGE_INTEGER li
,li2
;
375 struct timeval tv1
,tv2
;
376 gettimeofday(&tv1
,NULL
);
381 const char* input
= "1234-5678-1234-456";
382 size_t len
= strlen(input
);
385 ::QueryPerformanceCounter(&li
);
387 gettimeofday(&tv1
,NULL
);
389 for (int i
=0;i
<1000;++i
)
393 //for (size_t j=0;j<len;++j)
398 p
.process_event(char_0());
401 p
.process_event(char_1());
404 p
.process_event(char_2());
407 p
.process_event(char_3());
410 p
.process_event(char_4());
413 p
.process_event(char_5());
416 p
.process_event(char_6());
419 p
.process_event(char_7());
422 p
.process_event(char_8());
425 p
.process_event(char_9());
428 p
.process_event(event_char
<'-'>());
431 p
.process_event(default_char());
436 p
.process_event(eos());
437 p
.process_event(eos());
440 ::QueryPerformanceCounter(&li2
);
442 gettimeofday(&tv2
,NULL
);
445 std::cout
<< "msm(1) took in s:" << (double)(li2
.QuadPart
-li
.QuadPart
)/res
.QuadPart
<<"\n" <<std::endl
;
447 std::cout
<< "msm(1) took in us:" << mtime(tv1
,tv2
) <<"\n" <<std::endl
;
453 ::QueryPerformanceCounter(&li
);
455 gettimeofday(&tv1
,NULL
);
457 for (int i
=0;i
<1000;++i
)
459 for (size_t j
=0;j
<len
;++j
)
461 parse
.new_char(input
[j
]);
463 parse
.finish_string();
467 ::QueryPerformanceCounter(&li2
);
469 gettimeofday(&tv2
,NULL
);
472 std::cout
<< "msm(2) took in s:" << (double)(li2
.QuadPart
-li
.QuadPart
)/res
.QuadPart
<<"\n" <<std::endl
;
474 std::cout
<< "msm(2) took in us:" << mtime(tv1
,tv2
) <<"\n" <<std::endl
;
476 std::cout
<< "msm(3) took in s:" << time_match(input
) <<"\n" <<std::endl
;