Ticket #12411: BoostCoroutineTest.cpp

File BoostCoroutineTest.cpp, 6.7 KB (added by martin_haas@…, 6 years ago)

Source code to show coroutine issue

Line 
1#include <stdio.h>
2#include <tchar.h>
3
4#include <string>
5
6#include <boost/bind.hpp>
7#include <boost/coroutine/all.hpp>
8#include <boost/coroutine/attributes.hpp>
9#include <boost/coroutine/detail/flags.hpp>
10#include <boost/timer/timer.hpp>
11#include <boost/lexical_cast.hpp>
12#include <boost/chrono.hpp>
13#include <boost/math/distributions.hpp>
14#include <boost/random/variate_generator.hpp>
15#include <boost/random/mersenne_twister.hpp>
16#include <boost/random/uniform_int_distribution.hpp>
17#include <boost/random/uniform_real_distribution.hpp>
18#include <boost/random/triangle_distribution.hpp>
19#include <boost/random/exponential_distribution.hpp>
20#include <boost/random/gamma_distribution.hpp>
21#include <boost/random/normal_distribution.hpp>
22#include <boost/random/lognormal_distribution.hpp>
23
24using namespace std;
25
26///////////////////////////////////////////////////////////////////////////////
27class job
28{
29
30public:
31 job() {};
32 job(string _name, void(*processFunction)(boost::coroutines::symmetric_coroutine<job&>::yield_type&)) : name(_name), coroProc(processFunction), ID(nextID++)
33 {
34 nextEventTime = 0;
35 priority = 1;
36 }
37 ~job() {};
38
39 boost::coroutines::symmetric_coroutine<job&>::yield_type *yield;
40 boost::coroutines::symmetric_coroutine<job&>::call_type coroProc;
41
42 int ID;
43 static int nextID;
44 string name;
45 string STATUS;
46 int priority;
47 void setNextEventTime(double net) { nextEventTime = net; }
48 double getNextEventTime() { return nextEventTime; }
49
50private:
51 double nextEventTime;
52
53};
54///////////////////////////////////////////////////////////////////////////////
55
56///////////////////////////////////////////////////////////////////////////////
57bool compByNextEventTime(job* a, job* b)
58{
59 if (a->getNextEventTime() == b->getNextEventTime())
60 {
61 if (a->priority == b->priority)
62 {
63 return false;
64 }
65 else
66 {
67 return a->priority > b->priority;
68 }
69 }
70 else
71 {
72 return a->getNextEventTime() < b->getNextEventTime();
73 }
74}
75///////////////////////////////////////////////////////////////////////////////
76
77///////////////////////////////////////////////////////////////////////////////
78class jobShop
79{
80public:
81
82 jobShop()
83 {
84 modelTime = 0;;
85 }
86 ~jobShop() {};
87 jobShop(const jobShop& sM)
88 {
89 modelTime = sM.modelTime;
90 }
91
92 vector<job*> jobVector;
93 void insertProcess(job* j)
94 {
95 auto it = std::upper_bound(jobVector.begin(), jobVector.end(), j, compByNextEventTime);
96 jobVector.insert(it, j);
97 }
98
99 double simtime()
100 {
101 return modelTime;
102 }
103 void setModelTime(double mt) { modelTime = mt; }
104
105
106private:
107 double modelTime;
108};
109///////////////////////////////////////////////////////////////////////////////
110
111///////////////////////////////////////////////////////////////////////////////
112typedef boost::coroutines::symmetric_coroutine<void> coro_t;
113typedef boost::coroutines::symmetric_coroutine<job&> coro_simProcess_t;
114
115int job::nextID = 0;
116
117jobShop *m;
118boost::random::mt19937 gen;
119
120long uniform_int(long min, long max);
121void hold(double time);
122void createJob(string _name, void(*processFunction)(coro_simProcess_t::yield_type &yield));
123void activateNextJob();
124void jobCoroFn(coro_simProcess_t::yield_type &yield);
125void jobCoroFn2(coro_simProcess_t::yield_type &yield);
126
127///////////////////////////////////////////////////////////////////////////////
128long uniform_int(long min, long max)
129{
130 boost::random::uniform_int_distribution<> dist(min, max);
131 return dist(gen);
132}
133///////////////////////////////////////////////////////////////////////////////
134
135///////////////////////////////////////////////////////////////////////////////
136void hold(double time)
137{
138
139 job* j = m->jobVector.front();
140 m->jobVector.erase(m->jobVector.begin());
141
142 coro_simProcess_t::yield_type &yield = *j->yield;
143 j->setNextEventTime(time + m->simtime());
144 m->insertProcess(j);
145
146 yield();
147}
148///////////////////////////////////////////////////////////////////////////////
149
150///////////////////////////////////////////////////////////////////////////////
151void createJob(string _name, void(*processFunction)(coro_simProcess_t::yield_type &yield))
152{
153 job* j = new job(_name, processFunction);
154 j->setNextEventTime(m->simtime());
155 m->insertProcess(j);
156}
157///////////////////////////////////////////////////////////////////////////////
158
159///////////////////////////////////////////////////////////////////////////////
160void activateNextJob()
161{
162
163 while (!m->jobVector.empty())
164 {
165
166 job* j = m->jobVector.front();
167
168 m->setModelTime(j->getNextEventTime());
169 j->coroProc(*j);
170
171 if (j->STATUS == "COMPLETE")
172 {
173 m->jobVector.erase(m->jobVector.begin());
174 cout << endl;
175 cout << "Finished job " << j->name << " " << m->simtime() << endl;
176 cout << endl;
177 delete j;
178 }
179
180 }
181}
182///////////////////////////////////////////////////////////////////////////////
183
184///////////////////////////////////////////////////////////////////////////////
185void jobCoroFn(coro_simProcess_t::yield_type &yield)
186{
187
188 job& j = yield.get();
189 j.yield = &yield;
190
191 hold(0);
192
193 cout << j.name << " 1 " << m->simtime() << endl;
194 if (j.name == "P1")
195 hold(uniform_int(0, 10));
196 else
197 hold(10.0);
198
199 cout << j.name << " 2 " << m->simtime() << endl;
200 if (j.name == "P1")
201 hold(uniform_int(5, 10));
202 else
203 hold(10.0);
204
205 hold(0);
206 cout << j.name << " 3 " << m->simtime() << endl;
207 if (j.name == "P1")
208 hold(uniform_int(0, 10));
209 else
210 hold(10.0);
211
212 cout << j.name << " 4 " << m->simtime() << endl;
213 if (j.name == "P1")
214 hold(uniform_int(5, 10));
215 else
216 hold(10.00);
217
218 cout << j.name << " 5 " << m->simtime() << endl;
219 if (j.name == "P1")
220 hold(uniform_int(5, 10));
221 else
222 {
223 hold(10.0);
224 }
225
226 cout << j.name << " 6 " << m->simtime() << endl;
227
228 j.STATUS = "COMPLETE";
229}
230///////////////////////////////////////////////////////////////////////////////
231
232///////////////////////////////////////////////////////////////////////////////
233void jobCoroFn2(coro_simProcess_t::yield_type &yield)
234{
235 job& j = yield.get();
236 j.yield = &yield;
237
238 cout << j.name << " A " << m->simtime() << endl;
239 hold(uniform_int(1, 10));
240
241 cout << j.name << " B " << m->simtime() << endl;
242 createJob("P3", jobCoroFn);
243 hold(uniform_int(1, 10));
244
245 cout << j.name << " C " << m->simtime() << endl;
246 hold(uniform_int(5, 10));
247
248 cout << j.name << " D " << m->simtime() << endl;
249 j.STATUS = "COMPLETE";
250
251 j.yield;
252}
253///////////////////////////////////////////////////////////////////////////////
254
255int main()
256{
257 boost::timer::cpu_timer timer;
258
259 m = new jobShop();
260 gen.seed(49);
261
262 createJob("P1", jobCoroFn);
263 createJob("P2", jobCoroFn2);
264
265 activateNextJob();
266
267 cout << endl;
268 cout << "Simulation Finished" << endl;
269 std::cout << timer.format() << endl;
270
271 delete m;
272
273 getchar();
274 return 0;
275}
276