-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathboost_msm.cpp
More file actions
117 lines (99 loc) · 3.63 KB
/
boost_msm.cpp
File metadata and controls
117 lines (99 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// back-end
#include <boost/msm/back/state_machine.hpp>
// front-end
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/state_machine_def.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
// ---------------------------------------------------------------------------
// states
vector<string> state_names{"off hook"s, "connecting"s, "connected"s, "on hold"s,
"destroyed"s};
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// transitions/events
struct CallDialed {};
struct HungUp {};
struct CallConnected {};
struct PlacedOnHold {};
struct TakenOffHold {};
struct LeftMessage {};
struct PhoneThrownIntoWall {};
// ---------------------------------------------------------------------------
// Boost based FSM: CRTP on state_machine_def
struct PhoneStateMachine : state_machine_def<PhoneStateMachine> {
bool angry{true}; // start with false
// ---------------------------------------------------------------------------
// Define states
struct OffHook : state<> {};
struct Connecting : state<> {
template <class Event, class FSM> void on_entry(Event const &evt, FSM &) {
cout << "We are connecting..." << endl;
}
// also on_exit
};
struct Connected : state<> {};
struct OnHold : state<> {};
struct PhoneDestroyed : state<> {};
// ---------------------------------------------------------------------------
struct PhoneBeingDestroyed {
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const &, FSM &, SourceState &, TargetState &) {
cout << "Phone breaks into a million pieces" << endl;
}
};
struct CanDestroyPhone {
template <class EVT, class FSM, class SourceState, class TargetState>
bool operator()(EVT const &, FSM &fsm, SourceState &, TargetState &) {
return fsm.angry;
}
};
// ---------------------------------------------------------------------------
// Transition Table based on boost MPL:
// - vector of rows of type names!
// - extra conditions can be added.
// start, event, target, action, guard
struct transition_table
: mpl::vector<Row<OffHook, CallDialed, Connecting>,
Row<Connecting, CallConnected, Connected>,
Row<Connected, PlacedOnHold, OnHold>,
Row<OnHold, PhoneThrownIntoWall, PhoneDestroyed,
PhoneBeingDestroyed, // <--- transition handler!
CanDestroyPhone // <--- transition condition!
>> {};
// ---------------------------------------------------------------------------
// starting state
typedef OffHook initial_state;
// what happens if there's nowhere to go
template <class FSM, class Event>
void no_transition(Event const &e, FSM &, int state) {
cout << "No transition from state " << state_names[state] << " on event "
<< typeid(e).name() << endl;
}
};
int main() {
msm::back::state_machine<PhoneStateMachine> phone;
auto info = [&]() {
auto i = phone.current_state()[0];
cout << "The phone is currently " << state_names[i] << "\n";
};
info();
phone.process_event(CallDialed{});
info();
phone.process_event(CallConnected{});
info();
phone.process_event(PlacedOnHold{});
info();
phone.process_event(PhoneThrownIntoWall{});
info();
// try process_event here :)
phone.process_event(CallDialed{});
cout << "We are done using the phone"
<< "\n";
return 0;
}