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
00060 namespace ssim {
00061
00064 extern const char * Version;
00065
00068 typedef int ProcessId;
00069
00072 const ProcessId NULL_PROCESSID = -1;
00073
00088 typedef unsigned long Time;
00089
00092 const Time INIT_TIME = 0;
00093
00120 class Event {
00121 public:
00122 Event();
00123 virtual ~Event();
00124
00125 private:
00126 mutable unsigned refcount;
00127 friend class Sim;
00128 };
00129
00135 class Process {
00136 public:
00137 virtual ~Process();
00138
00147 virtual void init(void);
00148
00203 virtual void process_event(const Event * msg);
00204
00212 virtual void stop(void);
00213 };
00214
00221 class ProcessWithPId : public Process {
00222 public:
00234 ProcessId activate();
00235
00242 ProcessId pid() const;
00243
00244 ProcessWithPId();
00245
00246 private:
00247 ProcessId process_id;
00248 };
00249
00256 class Sim {
00257 public:
00267 static ProcessId create_process(Process *);
00268
00270 static int stop_process(ProcessId);
00272 static void stop_process();
00273
00284 static void clear();
00285
00295 static void self_signal_event(const Event *) throw();
00296
00305 static void self_signal_event(const Event *, Time delay) throw();
00306
00319 static int signal_event(ProcessId, const Event *) throw();
00331 static int signal_event(ProcessId, const Event *, Time) throw();
00332
00403 static void advance_delay(Time);
00404
00426 static ProcessId this_process();
00427
00445 static Time clock();
00446
00448 static void run_simulation();
00450 static void stop_simulation();
00451
00464 static void set_stop_time(Time t = INIT_TIME);
00465
00466 private:
00471 static Time current_time;
00473 static Time stop_time;
00475 static ProcessId current_process;
00477 static Time current_delay;
00479 static bool running;
00480
00481 enum ActionType { A_Event, A_Init, A_Stop };
00482
00483 struct Action {
00484 ActionType type;
00485 ProcessId pid;
00486 const Event * event;
00487
00488 Action(ActionType, ProcessId);
00489 Action(ActionType, ProcessId, const Event *);
00490
00491 Action(const Action &);
00492 Action & operator = (const Action &);
00493 };
00494
00495 typedef multimap<Time, Action> ActionsTable;
00496 static ActionsTable actions;
00497
00498 static void schedule(const Action &, Time);
00499 static void schedule_now(const Action &);
00500
00501 struct PDescr {
00502 Process * process;
00503 bool terminated;
00504 Time available_at;
00505
00506 PDescr(Process * p);
00507 };
00508
00509 typedef vector<PDescr> PsTable;
00510 static PsTable processes;
00511 };
00512
00513
00514
00515
00516 inline Event::Event(): refcount(0) {};
00517 inline Event::~Event() {};
00518
00519 inline Process::~Process() {};
00520
00521 inline void Process::init(void) {};
00522 inline void Process::stop(void) {};
00523 inline void Process::process_event(const Event *) {};
00524
00525 inline Sim::PDescr::PDescr(Process * p)
00526 : process(p), terminated(false), available_at(INIT_TIME) {}
00527
00528 inline Sim::Action::Action(ActionType i, ProcessId p, const Event *e)
00529 : type(i), pid(p), event(e) {}
00530
00531 inline Sim::Action::Action(ActionType i, ProcessId p)
00532 : type(i), pid(p), event((Event*)0) {}
00533
00534 inline Sim::Action::Action(const Action &a):
00535 type(a.type), pid(a.pid), event(a.event) {}
00536
00537 inline Sim::Action & Sim::Action::operator = (const Action &a) {
00538 type = a.type; pid = a.pid; event = a.event;
00539 return *this;
00540 }
00541
00542 inline void Sim::set_stop_time(Time t) {
00543 stop_time = t;
00544 }
00545
00546 inline void Sim::stop_process() {
00547 schedule_now(Action(A_Stop, current_process));
00548 }
00549
00550 inline int Sim::stop_process(ProcessId pid) {
00551 if (processes[pid].terminated) return -1;
00552 schedule_now(Action(A_Stop, pid));
00553 return 0;
00554 }
00555
00556 inline void Sim::stop_simulation() {
00557 running = false;
00558 }
00559
00560 inline void Sim::advance_delay(Time delay) {
00561 if (!running) return;
00562 current_delay += delay;
00563 }
00564
00565 inline ProcessId Sim::this_process() {
00566 return current_process;
00567 }
00568
00569 inline Time Sim::clock() {
00570 return current_time + current_delay;
00571 }
00572
00573 inline void Sim::self_signal_event(const Event * e) throw() {
00574 schedule_now(Action(A_Event, current_process, e));
00575 }
00576
00577 inline void Sim::self_signal_event(const Event * e, Time delay) throw() {
00578 schedule(Action(A_Event, current_process, e), delay);
00579 }
00580
00581 inline int Sim::signal_event(ProcessId pid, const Event * e) throw() {
00582 PDescr & pd = processes[current_process];
00583 if (pd.terminated) return -1;
00584 if (pd.available_at <= clock()) {
00585 schedule_now(Action(A_Event, pid, e));
00586 }
00587 return 0;
00588 }
00589
00590 inline int Sim::signal_event(ProcessId pid, const Event * e, Time d) throw() {
00591 PDescr & pd = processes[current_process];
00592 if (pd.terminated) return -1;
00593 if (pd.available_at <= clock() + d) {
00594 schedule(Action(A_Event, pid, e), d);
00595 }
00596 return 0;
00597 }
00598
00599 inline void Sim::schedule(const Action & action, Time t) {
00600 if (action.event != 0) { action.event->refcount++; }
00601 actions.insert(ActionsTable::value_type(clock() + t, action));
00602 }
00603
00604 inline void Sim::schedule_now(const Action & action) {
00605 if (action.event != 0) { action.event->refcount++; }
00606 actions.insert(actions.begin(), ActionsTable::value_type(clock(), action));
00607 }
00608
00609 inline ProcessId ProcessWithPId::activate() {
00610 if (process_id == NULL_PROCESSID) {
00611 return process_id = Sim::create_process(this);
00612 } else {
00613 return NULL_PROCESSID;
00614 }
00615 }
00616
00617 inline ProcessWithPId::ProcessWithPId(): process_id(NULL_PROCESSID) {};
00618
00619 inline ProcessId ProcessWithPId::pid() const {
00620 return process_id;
00621 }
00622
00623 };
00624
00625 #endif
00626