]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/msm/doc/PDF/examples/Serialize.cpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / msm / doc / PDF / examples / Serialize.cpp
CommitLineData
7c673cae
FG
1#include <iostream>
2// back-end
3#include <boost/msm/back/state_machine.hpp>
4//front-end
5#include <boost/msm/front/state_machine_def.hpp>
6
7// include headers that implement a archive in simple text format
8#include <boost/archive/text_oarchive.hpp>
9#include <boost/archive/text_iarchive.hpp>
10#include <boost/serialization/tracking.hpp>
11
12#include <fstream>
13
14
15namespace msm = boost::msm;
16namespace mpl = boost::mpl;
17
18
19namespace
20{
21 // events
22 struct play {};
23 struct end_pause {};
24 struct stop {};
25 struct pause {};
26 struct open_close {};
27
28 // A "complicated" event type that carries some data.
29 enum DiskTypeEnum
30 {
31 DISK_CD=0,
32 DISK_DVD=1
33 };
34 struct cd_detected
35 {
36 cd_detected(std::string name, DiskTypeEnum diskType)
37 : name(name),
38 disc_type(diskType)
39 {}
40
41 std::string name;
42 DiskTypeEnum disc_type;
43 };
44
45 // front-end: define the FSM structure
46 struct player_ : public msm::front::state_machine_def<player_>
47 {
48 //we might want to serialize some data contained by the front-end
49 int front_end_data;
50 player_():front_end_data(0){}
51 // to achieve this, ask for it
52 typedef int do_serialize;
53 // and provide a serialize
54 template<class Archive>
55 void serialize(Archive & ar, const unsigned int )
56 {
57 ar & front_end_data;
58 }
59 // The list of FSM states
60 struct Empty : public msm::front::state<>
61 {
62 // we want Empty to be serialized
63 typedef int do_serialize;
64 template<class Archive>
65 void serialize(Archive & ar, const unsigned int )
66 {
67 ar & some_dummy_data;
68 }
69 Empty():some_dummy_data(0){}
70 // every (optional) entry/exit methods get the event passed.
71 template <class Event,class FSM>
72 void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
73 template <class Event,class FSM>
74 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
75 int some_dummy_data;
76 };
77 struct Open : public msm::front::state<>
78 {
79 template <class Event,class FSM>
80 void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
81 template <class Event,class FSM>
82 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
83 };
84
85 // sm_ptr still supported but deprecated as functors are a much better way to do the same thing
86 struct Stopped : public msm::front::state<msm::front::default_base_state,msm::front::sm_ptr>
87 {
88 template <class Event,class FSM>
89 void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
90 template <class Event,class FSM>
91 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
92 void set_sm_ptr(player_* pl)
93 {
94 m_player=pl;
95 }
96 player_* m_player;
97 };
98
99 struct Playing : public msm::front::state<>
100 {
101 template <class Event,class FSM>
102 void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
103 template <class Event,class FSM>
104 void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
105 };
106
107 // state not defining any entry or exit
108 struct Paused : public msm::front::state<>
109 {
110 };
111
112 // the initial state of the player SM. Must be defined
113 typedef Empty initial_state;
114
115 // transition actions
116 void start_playback(play const&) { std::cout << "player::start_playback\n"; }
117 void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; }
118 void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; }
119 void store_cd_info(cd_detected const&) { std::cout << "player::store_cd_info\n"; }
120 void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; }
121 void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; }
122 void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; }
123 void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; }
124 void stopped_again(stop const&) {std::cout << "player::stopped_again\n";}
125 // guard conditions
126 bool good_disk_format(cd_detected const& evt)
127 {
128 // to test a guard condition, let's say we understand only CDs, not DVD
129 if (evt.disc_type != DISK_CD)
130 {
131 std::cout << "wrong disk, sorry" << std::endl;
132 return false;
133 }
134 return true;
135 }
136 // used to show a transition conflict. This guard will simply deactivate one transition and thus
137 // solve the conflict
138 bool auto_start(cd_detected const&)
139 {
140 return false;
141 }
142
143 typedef player_ p; // makes transition table cleaner
144
145 // Transition table for player
146 struct transition_table : mpl::vector<
147 // Start Event Next Action Guard
148 // +---------+-------------+---------+---------------------+----------------------+
149 a_row < Stopped , play , Playing , &p::start_playback >,
150 a_row < Stopped , open_close , Open , &p::open_drawer >,
151 _row < Stopped , stop , Stopped >,
152 // +---------+-------------+---------+---------------------+----------------------+
153 a_row < Open , open_close , Empty , &p::close_drawer >,
154 // +---------+-------------+---------+---------------------+----------------------+
155 a_row < Empty , open_close , Open , &p::open_drawer >,
156 row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >,
157 row < Empty , cd_detected , Playing , &p::store_cd_info ,&p::auto_start >,
158 // +---------+-------------+---------+---------------------+----------------------+
159 a_row < Playing , stop , Stopped , &p::stop_playback >,
160 a_row < Playing , pause , Paused , &p::pause_playback >,
161 a_row < Playing , open_close , Open , &p::stop_and_open >,
162 // +---------+-------------+---------+---------------------+----------------------+
163 a_row < Paused , end_pause , Playing , &p::resume_playback >,
164 a_row < Paused , stop , Stopped , &p::stop_playback >,
165 a_row < Paused , open_close , Open , &p::stop_and_open >
166 // +---------+-------------+---------+---------------------+----------------------+
167 > {};
168 // Replaces the default no-transition response.
169 template <class FSM,class Event>
170 void no_transition(Event const& e, FSM&,int state)
171 {
172 std::cout << "no transition from state " << state
173 << " on event " << typeid(e).name() << std::endl;
174 }
175 };
176 // Pick a back-end
177 typedef msm::back::state_machine<player_> player;
178
179 //
180 // Testing utilities.
181 //
182 static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
183 void pstate(player const& p)
184 {
185 std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
186 }
187
188 void test()
189 {
190 player p;
191 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
192 p.start();
193 p.get_state<player_::Empty&>().some_dummy_data=3;
194 p.front_end_data=4;
195
196 // go to Open, call on_exit on Empty, then action, then on_entry on Open
197 p.process_event(open_close()); pstate(p);
198
199 std::ofstream ofs("fsm.txt");
200 // save fsm to archive (current state is Open)
201 {
202 boost::archive::text_oarchive oa(ofs);
203 // write class instance to archive
204 oa << p;
205 }
206 // reload fsm in state Open
207 player p2;
208 {
209 // create and open an archive for input
210 std::ifstream ifs("fsm.txt");
211 boost::archive::text_iarchive ia(ifs);
212 // read class state from archive
213 ia >> p2;
214 }
215 // we now use p2 as it was loaded
216 // check that we kept Empty's data value
217 std::cout << "Empty's data should be 3:" << p2.get_state<player_::Empty&>().some_dummy_data << std::endl;
218 std::cout << "front-end data should be 4:" << p2.front_end_data << std::endl;
219
220 p2.process_event(open_close()); pstate(p2);
221 // will be rejected, wrong disk type
222 p2.process_event(
223 cd_detected("louie, louie",DISK_DVD)); pstate(p2);
224 p2.process_event(
225 cd_detected("louie, louie",DISK_CD)); pstate(p2);
226 p2.process_event(play());
227
228 // at this point, Play is active
229 p2.process_event(pause()); pstate(p2);
230 // go back to Playing
231 p2.process_event(end_pause()); pstate(p2);
232 p2.process_event(pause()); pstate(p2);
233 p2.process_event(stop()); pstate(p2);
234 // event leading to the same state
235 // no action method called as it is not present in the transition table
236 p2.process_event(stop()); pstate(p2);
237 }
238}
239// eliminate object tracking (even if serialized through a pointer)
240// at the risk of a programming error creating duplicate objects.
241// this is to get rid of warning because p is not const
242BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
243
244int main()
245{
246 test();
247 return 0;
248}