Boost的状态机库教程 补充
来自:http://www.cppblog.com/shanoa/archive/2009/05/30/86143.html
接触了boost的状态机,发现不是想象中的那么好用,在一些地方还得用上mpl库里的东西,由于对模板元编程不是很熟练,搞了好些天才算弄明白这该死的mpl::list的原理和用法。
boost的状态机是属于静态链接的状态机,也就是说,它的图结构是编译期间就确定了的,在运行时不可以动态配置。所以,它的用途是有一定局限性的,但在一般情况下,它不仅很通用,而且在你会用并熟练地情况下,还会很好用,用起来很舒服,逻辑也很合理。下面就是一段代码,当然也是借鉴了别人的东西,自己修改了一下,在MainState中添加了一个Transition做了测试,因为此前我还不知道一个状态如何包含多个Transition,呵呵,原来是用mpl::list来做。至于这个状态机的入门教程,网上随处可见的三部曲:《boost 状态机入门教程》说得很清楚。
1
#include
<
iostream
>
2 #include < ctime >
3
4 #include < boost / statechart / transition.hpp >
5 #include < boost / statechart / event .hpp >
6 #include < boost / statechart / state_machine.hpp >
7 #include < boost / statechart / simple_state.hpp >
8
9 namespace sc = boost::statechart;
10
11
12
13 class EvtStartStop : public sc:: event < EvtStartStop > {};
14 class EvtReset : public sc:: event < EvtReset > {};
15 class EvtGo : public sc:: event < EvtGo > {};
16
17
18 class MainState;
19 class StopState;
20 class RunState;
21 class TwoState;
22
23 class Machine : public sc::state_machine < Machine, MainState >
24 {};
25
26
27
28
29
30
31 class MainState : public sc::simple_state < MainState, Machine, StopState >
32 {
33 public :
34 typedef sc::transition < EvtReset, MainState > reactReset;
35 typedef sc::transition < EvtGo, TwoState > reactGo;
36 typedef boost::mpl::list < reactReset, reactGo > reactions;
37
38 MainState( void ){
39 std::cout << " 进入MainState " << std::endl;
40 mTime = 0 ;
41 }
42
43 ~ MainState( void ){
44 std::cout << " 退出MainState " << std::endl;
45 }
46
47 double mTime;
48 };
49
50
51 // 该状态属于无用状态,用于测试mpl::list的多transition用法
52 class TwoState : public sc::simple_state < TwoState, Machine >
53 {
54 public :
55 typedef sc::transition < EvtGo, MainState > reactions;
56
57 TwoState( void ){
58 std::cout << " 进入TwoState " << std::endl;
59 }
60
61 ~ TwoState( void ){
62 std::cout << " 退出TwoState " << std::endl;
63 }
64 };
65
66
67 class StopState : public sc::simple_state < StopState, MainState >
68 {
69 public :
70 typedef sc::transition < EvtStartStop, RunState > reactions;
71 StopState( void ){
72 std::cout << " 进入StopState " << std::endl;
73 }
74
75 ~ StopState( void ){
76 std::cout << " 退出StopState " << std::endl;
77 }
78 };
79
80 class RunState : public sc::simple_state < RunState, MainState >
81 {
82 public :
83 typedef sc::transition < EvtStartStop, StopState > reactions;
84 RunState( void ){
85 std::cout << " 进入RunState " << std::endl;
86 mStartTime = 0 ;
87 }
88
89 ~ RunState( void ){
90 std::cout << " 退出RunState " << std::endl;
91 context < MainState > ().mTime += std::difftime(std::time( 0 ), mStartTime);
92 }
93
94 std::time_t mStartTime;
95 };
96
97
98 int _tmain( int argc, _TCHAR * argv[])
99 {
100 Machine mc;
101 mc.initiate();
102
103 mc.process_event(EvtStartStop());
104 mc.process_event(EvtStartStop());
105 mc.process_event(EvtReset());
106 mc.process_event(EvtGo());
107 mc.process_event(EvtGo());
108
109 return 0 ;
110 }
2 #include < ctime >
3
4 #include < boost / statechart / transition.hpp >
5 #include < boost / statechart / event .hpp >
6 #include < boost / statechart / state_machine.hpp >
7 #include < boost / statechart / simple_state.hpp >
8
9 namespace sc = boost::statechart;
10
11
12
13 class EvtStartStop : public sc:: event < EvtStartStop > {};
14 class EvtReset : public sc:: event < EvtReset > {};
15 class EvtGo : public sc:: event < EvtGo > {};
16
17
18 class MainState;
19 class StopState;
20 class RunState;
21 class TwoState;
22
23 class Machine : public sc::state_machine < Machine, MainState >
24 {};
25
26
27
28
29
30
31 class MainState : public sc::simple_state < MainState, Machine, StopState >
32 {
33 public :
34 typedef sc::transition < EvtReset, MainState > reactReset;
35 typedef sc::transition < EvtGo, TwoState > reactGo;
36 typedef boost::mpl::list < reactReset, reactGo > reactions;
37
38 MainState( void ){
39 std::cout << " 进入MainState " << std::endl;
40 mTime = 0 ;
41 }
42
43 ~ MainState( void ){
44 std::cout << " 退出MainState " << std::endl;
45 }
46
47 double mTime;
48 };
49
50
51 // 该状态属于无用状态,用于测试mpl::list的多transition用法
52 class TwoState : public sc::simple_state < TwoState, Machine >
53 {
54 public :
55 typedef sc::transition < EvtGo, MainState > reactions;
56
57 TwoState( void ){
58 std::cout << " 进入TwoState " << std::endl;
59 }
60
61 ~ TwoState( void ){
62 std::cout << " 退出TwoState " << std::endl;
63 }
64 };
65
66
67 class StopState : public sc::simple_state < StopState, MainState >
68 {
69 public :
70 typedef sc::transition < EvtStartStop, RunState > reactions;
71 StopState( void ){
72 std::cout << " 进入StopState " << std::endl;
73 }
74
75 ~ StopState( void ){
76 std::cout << " 退出StopState " << std::endl;
77 }
78 };
79
80 class RunState : public sc::simple_state < RunState, MainState >
81 {
82 public :
83 typedef sc::transition < EvtStartStop, StopState > reactions;
84 RunState( void ){
85 std::cout << " 进入RunState " << std::endl;
86 mStartTime = 0 ;
87 }
88
89 ~ RunState( void ){
90 std::cout << " 退出RunState " << std::endl;
91 context < MainState > ().mTime += std::difftime(std::time( 0 ), mStartTime);
92 }
93
94 std::time_t mStartTime;
95 };
96
97
98 int _tmain( int argc, _TCHAR * argv[])
99 {
100 Machine mc;
101 mc.initiate();
102
103 mc.process_event(EvtStartStop());
104 mc.process_event(EvtStartStop());
105 mc.process_event(EvtReset());
106 mc.process_event(EvtGo());
107 mc.process_event(EvtGo());
108
109 return 0 ;
110 }