1 | #include <iostream>
|
---|
2 |
|
---|
3 | #include <boost/bind.hpp>
|
---|
4 | #include <boost/msm/back/state_machine.hpp>
|
---|
5 | #include <boost/msm/front/state_machine_def.hpp>
|
---|
6 | #include <boost/shared_ptr.hpp>
|
---|
7 |
|
---|
8 | namespace msm = boost::msm;
|
---|
9 | namespace mpl = boost::mpl;
|
---|
10 |
|
---|
11 | struct cmd_t {
|
---|
12 | cmd_t(int id) : id_(id) {}
|
---|
13 | virtual ~cmd_t() {}
|
---|
14 |
|
---|
15 | int id_;
|
---|
16 | };
|
---|
17 |
|
---|
18 | struct test_machine_front_t : public msm::front::state_machine_def<test_machine_front_t> {
|
---|
19 |
|
---|
20 | struct ev_connected {};
|
---|
21 | struct ev_disconnected {};
|
---|
22 |
|
---|
23 | // internal connected state events
|
---|
24 | struct ev_async_send_simple_cmd
|
---|
25 | {
|
---|
26 | ev_async_send_simple_cmd(boost::shared_ptr<cmd_t> op) : op_(op) {}
|
---|
27 | boost::shared_ptr<cmd_t> op_;
|
---|
28 | };
|
---|
29 |
|
---|
30 | struct ev_async_send_cmd_with_reply
|
---|
31 | {
|
---|
32 | ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t> op) : op_(op) {}
|
---|
33 | boost::shared_ptr<cmd_t> op_;
|
---|
34 | };
|
---|
35 |
|
---|
36 | struct ev_async_got_reply {};
|
---|
37 |
|
---|
38 | // disconnected state
|
---|
39 | struct st_disconnected : public msm::front::state<> {};
|
---|
40 |
|
---|
41 | // connected state is submachine
|
---|
42 | // front-end st_connected_
|
---|
43 | struct st_connected_ : public msm::front::state_machine_def<st_connected_>
|
---|
44 | {
|
---|
45 | struct st_ready : public msm::front::state<> {};
|
---|
46 |
|
---|
47 | struct st_busy : public msm::front::state<>
|
---|
48 | {
|
---|
49 | typedef mpl::vector<ev_async_send_simple_cmd, ev_async_send_cmd_with_reply> deferred_events;
|
---|
50 | };
|
---|
51 |
|
---|
52 | // the initial state of st_connected_
|
---|
53 | typedef st_ready initial_state;
|
---|
54 |
|
---|
55 | void on_simple_cmd( const ev_async_send_simple_cmd& ev )
|
---|
56 | {
|
---|
57 | std::cout << "On simple cmd: " << ev.op_ << std::endl;
|
---|
58 |
|
---|
59 | op_ = ev.op_;
|
---|
60 | }
|
---|
61 |
|
---|
62 | void on_cmd_with_reply( const ev_async_send_cmd_with_reply& ev )
|
---|
63 | {
|
---|
64 | std::cout << "On cmd with reply: " << ev.op_->id_ << std::endl;
|
---|
65 | op_ = ev.op_;
|
---|
66 | }
|
---|
67 |
|
---|
68 | void on_got_reply( const ev_async_got_reply& )
|
---|
69 | {
|
---|
70 | // std::cout << "On got reply" << std::endl;
|
---|
71 | op_.reset();
|
---|
72 | }
|
---|
73 |
|
---|
74 | template <class Event, class Fsm>
|
---|
75 | void on_exit(Event const&, Fsm&)
|
---|
76 | {
|
---|
77 | std::cout << "On exit" << std::endl;
|
---|
78 | op_.reset();
|
---|
79 | }
|
---|
80 |
|
---|
81 | typedef st_connected_ m;
|
---|
82 |
|
---|
83 | // transition table for st_connected_
|
---|
84 | struct transition_table : mpl::vector<
|
---|
85 | // Start Event Next Action Guard
|
---|
86 | // +---------+-----------------------------+---------+----------------------+----------------+
|
---|
87 | a_row < st_ready, ev_async_send_cmd_with_reply, st_busy , &m::on_cmd_with_reply>,
|
---|
88 | a_row < st_ready, ev_async_send_simple_cmd , st_ready, &m::on_simple_cmd >,
|
---|
89 | a_row < st_busy , ev_async_got_reply , st_ready, &m::on_got_reply >
|
---|
90 | // +---------+-----------------------------+---------+----------------------+----------------+
|
---|
91 | > {};
|
---|
92 |
|
---|
93 | typedef int no_message_queue;
|
---|
94 | typedef int no_exception_thrown;
|
---|
95 |
|
---|
96 | boost::shared_ptr<cmd_t> op_;
|
---|
97 | };
|
---|
98 |
|
---|
99 | // back-end st_connected_
|
---|
100 | typedef msm::back::state_machine<st_connected_> st_connected;
|
---|
101 |
|
---|
102 | // the initial state of machine_
|
---|
103 | typedef st_disconnected initial_state;
|
---|
104 |
|
---|
105 | // transition table for machine_
|
---|
106 | struct transition_table : mpl::vector<
|
---|
107 | // Start Event Next Action Guard
|
---|
108 | // +---------------+----------------+-----------------+--------------------+----------------------+
|
---|
109 | _row < st_disconnected, ev_connected , st_connected >,
|
---|
110 | _row < st_connected , ev_disconnected, st_disconnected >
|
---|
111 | // +---------------+----------------+-----------------+--------------------+----------------------+
|
---|
112 | > {};
|
---|
113 |
|
---|
114 | // replaces the default no-transition response.
|
---|
115 | template <class FSM,class Event>
|
---|
116 | void no_transition(Event const&, FSM&, int)
|
---|
117 | {
|
---|
118 | assert("Client FSM no_transition");
|
---|
119 | }
|
---|
120 |
|
---|
121 | typedef int no_message_queue;
|
---|
122 | typedef int no_exception_thrown;
|
---|
123 | };
|
---|
124 |
|
---|
125 | struct test_machine_t : public msm::back::state_machine<test_machine_front_t, std::deque<boost::function<boost::msm::back::HandledEnum()> > > {};
|
---|
126 |
|
---|
127 | int main(int argc, char* argv[])
|
---|
128 | {
|
---|
129 | test_machine_t machine;
|
---|
130 |
|
---|
131 | machine.process_event(test_machine_front_t::ev_connected());
|
---|
132 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(0))));
|
---|
133 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(1))));
|
---|
134 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(2))));
|
---|
135 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(3))));
|
---|
136 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(4))));
|
---|
137 | machine.process_event(test_machine_front_t::ev_disconnected());
|
---|
138 | machine.process_event(test_machine_front_t::ev_connected());
|
---|
139 | machine.process_event(test_machine_front_t::ev_async_send_cmd_with_reply(boost::shared_ptr<cmd_t>(new cmd_t(5))));
|
---|
140 | machine.process_event(test_machine_front_t::ev_async_got_reply());
|
---|
141 | return 0;
|
---|
142 | }
|
---|