| 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 | }
|
|---|