00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _ssim_h
00031 #define _ssim_h
00032
00033 #include <vector>
00034 #include <map>
00035
00036 using std::multimap;
00037 using std::map;
00038 using std::vector;
00039
00139 namespace ssim {
00140
00143 extern const char * Version;
00144
00147 typedef unsigned long ProcessId;
00148
00151 const ProcessId NULL_PROCESSID = 0;
00152
00163 typedef unsigned long Time;
00164
00167 const Time INIT_TIME = 0;
00168
00175 typedef unsigned EventType;
00176
00186 class Event {
00187 public:
00190 EventType type;
00191
00192 Event();
00193 Event(EventType);
00194 virtual ~Event();
00195
00196 private:
00197 mutable unsigned refcount;
00198 friend class Sim;
00199 };
00200
00206 class Process {
00207 public:
00208 virtual ~Process();
00209
00216 virtual void init(void);
00217
00236 virtual void process_event(const Event * msg);
00237
00249 virtual void process_timeout();
00250
00258 virtual void stop(void);
00259 };
00260
00267 class ProcessWithPId : public Process {
00268 public:
00280 ProcessId activate(char mode = 0);
00281
00288 ProcessId pid() const;
00289
00290 ProcessWithPId();
00291
00292 private:
00293 ProcessId process_id;
00294 };
00295
00302 class Sim {
00303 public:
00320 static ProcessId create_process(Process *, char mode = 0);
00321
00323 static const char P_SEQUENTIAL = 0x02;
00325 static const char P_QUEUING = 0x04;
00326
00328 static int stop_process(ProcessId);
00330 static void stop_process();
00331
00342 static void clear();
00343
00351 static int signal_event(const Event *, ProcessId);
00356 static int signal_event(const Event *, ProcessId, Time);
00357
00363 static void set_timeout(Time);
00364
00398 static void advance_delay(Time);
00399
00409 static ProcessId this_process();
00410
00425 static Time clock();
00426
00428 static void run_simulation();
00430 static void stop_simulation();
00431
00432 private:
00437 static Time current_time;
00439 static ProcessId current_process;
00441 static Time current_delay;
00443 static bool running;
00444
00445 enum ActionType { A_Event, A_Timeout, A_Init, A_Stop };
00446
00447 struct Action {
00448 ActionType type;
00449 ProcessId pid;
00450 const Event * event;
00451
00452 Action(ActionType, ProcessId);
00453 Action(ActionType, ProcessId, const Event *);
00454
00455 Action(const Action &);
00456 Action & operator = (const Action &);
00457 };
00458
00459 typedef multimap<Time, Action> ActionsTable;
00460 static ActionsTable actions;
00461
00462 static void schedule(const Action &, Time);
00463 static void schedule_now(const Action &);
00464
00465
00466
00467
00468 static const char P_TERMINATED = 0x01;
00469
00470 struct PDescr {
00471 Process * process;
00472 unsigned char status;
00473 Time total_action_time;
00474 Time available_at;
00475
00476 PDescr();
00477 PDescr(Process * p, char mode);
00478 };
00479
00480 typedef vector<PDescr> PsTable;
00481 static PsTable processes;
00482 };
00483
00484
00485
00486
00487 inline Event::Event(): refcount(0) {};
00488 inline Event::Event(EventType t): type(t), refcount(0) {};
00489 inline Event::~Event() {};
00490
00491 inline Process::~Process() {};
00492
00493 inline void Process::init(void) {};
00494 inline void Process::stop(void) {};
00495 inline void Process::process_event(const Event *) {};
00496 inline void Process::process_timeout() {};
00497
00498 inline Sim::PDescr::PDescr():
00499 process((Process*)0), status(P_TERMINATED),
00500 total_action_time(INIT_TIME), available_at(INIT_TIME) {};
00501
00502 inline Sim::PDescr::PDescr(Process * p, char mode):
00503 process(p), status(mode),
00504 total_action_time(INIT_TIME), available_at(INIT_TIME) {};
00505
00506 inline Sim::Action::Action(ActionType i, ProcessId p, const Event *e):
00507 type(i), pid(p), event(e) {}
00508
00509 inline Sim::Action::Action(ActionType i, ProcessId p):
00510 type(i), pid(p), event((Event*)0) {}
00511
00512 inline Sim::Action::Action(const Action &a):
00513 type(a.type), pid(a.pid), event(a.event) {}
00514
00515 inline Sim::Action & Sim::Action::operator = (const Action &a) {
00516 type = a.type; pid = a.pid; event = a.event;
00517 return *this;
00518 }
00519
00520 inline void Sim::set_timeout(Time t) {
00521 schedule(Action(A_Timeout, current_process), t);
00522 }
00523
00524 inline void Sim::stop_process() {
00525 schedule_now(Action(A_Stop, current_process));
00526 }
00527
00528 inline int Sim::stop_process(ProcessId pid) {
00529 if (processes[pid].status & P_TERMINATED) return -1;
00530 schedule_now(Action(A_Stop, pid));
00531 return 0;
00532 }
00533
00534 inline void Sim::stop_simulation() {
00535 running = false;
00536 }
00537
00538 inline void Sim::advance_delay(Time delay) {
00539 if (!running) return;
00540 processes[current_process].total_action_time += delay;
00541 current_delay += delay;
00542 }
00543
00544 inline ProcessId Sim::this_process() {
00545 return current_process;
00546 }
00547
00548 inline Time Sim::clock() {
00549 return current_time + current_delay;
00550 }
00551
00552 inline int Sim::signal_event(const Event * e, ProcessId pid) {
00553 if (processes[pid].status & P_TERMINATED) return -1;
00554 schedule_now(Action(A_Event, pid, e));
00555 e->refcount++;
00556 return 0;
00557 }
00558
00559 inline int Sim::signal_event(const Event * e, ProcessId pid, Time delay) {
00560 if (processes[pid].status & P_TERMINATED) return -1;
00561 schedule(Action(A_Event, pid, e), delay);
00562 e->refcount++;
00563 return 0;
00564 }
00565
00566 inline void Sim::schedule(const Action & action, Time t) {
00567 actions.insert(ActionsTable::value_type(clock() + t, action));
00568 }
00569
00570 inline void Sim::schedule_now(const Action & action) {
00571 actions.insert(actions.begin(), ActionsTable::value_type(clock(), action));
00572 }
00573
00574 inline ProcessId ProcessWithPId::activate(char mode) {
00575 if (process_id == NULL_PROCESSID) {
00576 return process_id = Sim::create_process(this, mode);
00577 } else {
00578 return NULL_PROCESSID;
00579 }
00580 }
00581
00582 inline ProcessWithPId::ProcessWithPId(): process_id(NULL_PROCESSID) {};
00583
00584 inline ProcessId ProcessWithPId::pid() const {
00585 return process_id;
00586 }
00587
00588 };
00589
00590 #endif
00591