#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; /////////////////////////////////////////////////////////////////////////////// class job { public: job() {}; job(string _name, void(*processFunction)(boost::coroutines::symmetric_coroutine::yield_type&)) : name(_name), coroProc(processFunction), ID(nextID++) { nextEventTime = 0; priority = 1; } ~job() {}; boost::coroutines::symmetric_coroutine::yield_type *yield; boost::coroutines::symmetric_coroutine::call_type coroProc; int ID; static int nextID; string name; string STATUS; int priority; void setNextEventTime(double net) { nextEventTime = net; } double getNextEventTime() { return nextEventTime; } private: double nextEventTime; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool compByNextEventTime(job* a, job* b) { if (a->getNextEventTime() == b->getNextEventTime()) { if (a->priority == b->priority) { return false; } else { return a->priority > b->priority; } } else { return a->getNextEventTime() < b->getNextEventTime(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class jobShop { public: jobShop() { modelTime = 0;; } ~jobShop() {}; jobShop(const jobShop& sM) { modelTime = sM.modelTime; } vector jobVector; void insertProcess(job* j) { auto it = std::upper_bound(jobVector.begin(), jobVector.end(), j, compByNextEventTime); jobVector.insert(it, j); } double simtime() { return modelTime; } void setModelTime(double mt) { modelTime = mt; } private: double modelTime; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// typedef boost::coroutines::symmetric_coroutine coro_t; typedef boost::coroutines::symmetric_coroutine coro_simProcess_t; int job::nextID = 0; jobShop *m; boost::random::mt19937 gen; long uniform_int(long min, long max); void hold(double time); void createJob(string _name, void(*processFunction)(coro_simProcess_t::yield_type &yield)); void activateNextJob(); void jobCoroFn(coro_simProcess_t::yield_type &yield); void jobCoroFn2(coro_simProcess_t::yield_type &yield); /////////////////////////////////////////////////////////////////////////////// long uniform_int(long min, long max) { boost::random::uniform_int_distribution<> dist(min, max); return dist(gen); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void hold(double time) { job* j = m->jobVector.front(); m->jobVector.erase(m->jobVector.begin()); coro_simProcess_t::yield_type &yield = *j->yield; j->setNextEventTime(time + m->simtime()); m->insertProcess(j); yield(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void createJob(string _name, void(*processFunction)(coro_simProcess_t::yield_type &yield)) { job* j = new job(_name, processFunction); j->setNextEventTime(m->simtime()); m->insertProcess(j); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void activateNextJob() { while (!m->jobVector.empty()) { job* j = m->jobVector.front(); m->setModelTime(j->getNextEventTime()); j->coroProc(*j); if (j->STATUS == "COMPLETE") { m->jobVector.erase(m->jobVector.begin()); cout << endl; cout << "Finished job " << j->name << " " << m->simtime() << endl; cout << endl; delete j; } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void jobCoroFn(coro_simProcess_t::yield_type &yield) { job& j = yield.get(); j.yield = &yield; hold(0); cout << j.name << " 1 " << m->simtime() << endl; if (j.name == "P1") hold(uniform_int(0, 10)); else hold(10.0); cout << j.name << " 2 " << m->simtime() << endl; if (j.name == "P1") hold(uniform_int(5, 10)); else hold(10.0); hold(0); cout << j.name << " 3 " << m->simtime() << endl; if (j.name == "P1") hold(uniform_int(0, 10)); else hold(10.0); cout << j.name << " 4 " << m->simtime() << endl; if (j.name == "P1") hold(uniform_int(5, 10)); else hold(10.00); cout << j.name << " 5 " << m->simtime() << endl; if (j.name == "P1") hold(uniform_int(5, 10)); else { hold(10.0); } cout << j.name << " 6 " << m->simtime() << endl; j.STATUS = "COMPLETE"; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void jobCoroFn2(coro_simProcess_t::yield_type &yield) { job& j = yield.get(); j.yield = &yield; cout << j.name << " A " << m->simtime() << endl; hold(uniform_int(1, 10)); cout << j.name << " B " << m->simtime() << endl; createJob("P3", jobCoroFn); hold(uniform_int(1, 10)); cout << j.name << " C " << m->simtime() << endl; hold(uniform_int(5, 10)); cout << j.name << " D " << m->simtime() << endl; j.STATUS = "COMPLETE"; j.yield; } /////////////////////////////////////////////////////////////////////////////// int main() { boost::timer::cpu_timer timer; m = new jobShop(); gen.seed(49); createJob("P1", jobCoroFn); createJob("P2", jobCoroFn2); activateNextJob(); cout << endl; cout << "Simulation Finished" << endl; std::cout << timer.format() << endl; delete m; getchar(); return 0; }