00001
00024 #ifndef _ABS_SIMOBJECT_H_
00025 #define _ABS_SIMOBJECT_H_
00026
00027
00028
00029 #include <vector>
00030 #include <queue>
00031 #include <algorithm>
00032
00033 #include <cassert>
00034
00035 #include "Galois/Graphs/Graph.h"
00036
00037 #include "comDefs.h"
00038 #include "Event.h"
00039
00040
00041 #include "SimObject.h"
00042
00043
00044
00052 class AbstractSimObject: public SimObject {
00053 private:
00054
00059 template <typename T, typename Cmp>
00060 class CustomPriorityQueue {
00061
00062 Cmp cmp;
00063 std::vector<T> vec;
00064
00065 public:
00066 typedef std::vector<T> container_type;
00067
00068 typedef typename container_type::value_type value_type;
00069 typedef typename container_type::reference reference;
00070 typedef typename container_type::const_reference const_reference;
00071 typedef typename container_type::size_type size_type;
00072
00073
00074 CustomPriorityQueue (const Cmp& cmp = Cmp(), const std::vector<T>& vec = std::vector<T>())
00075 : cmp(cmp), vec(vec) {
00076 std::make_heap ( this->vec.begin (), this->vec.end (), cmp);
00077 }
00078
00079 template <typename Iter>
00080 CustomPriorityQueue (Iter b, Iter e, const Cmp& cmp = Cmp ()) : cmp (cmp) {
00081 vec.insert (vec.end (), b, e);
00082
00083 std::make_heap (vec.begin (), vec.end (), cmp);
00084 }
00085
00086 CustomPriorityQueue (const CustomPriorityQueue& that): cmp(that.cmp), vec (that.vec) {
00087 }
00088
00089
00090 bool empty () const {
00091 return vec.empty ();
00092 }
00093
00094 size_type size () const {
00095 return vec.size ();
00096 }
00097
00098 const_reference top () const {
00099 return vec.front ();
00100 }
00101
00102 void push (const value_type& x) {
00103 vec.push_back (x);
00104 std::push_heap (vec.begin (), vec.end (), cmp);
00105 }
00106
00107 void pop () {
00108 std::pop_heap (vec.begin (), vec.end (), cmp);
00109
00110 vec.pop_back ();
00111 }
00112
00113 void reserve (size_type s) {
00114 assert (s > 0);
00115 vec.reserve (s);
00116 }
00117
00118 };
00119
00120 public:
00125 static size_t NEVENTS_PER_ITER;
00126
00127
00128 private:
00129
00130 static const bool DEBUG = false;
00131
00133 static const size_t PQ_OVER_RESERVE = 1024;
00134
00135
00136 typedef CustomPriorityQueue<EventTy, EventRecvTimeLocalTieBrkCmp<EventTy> > PriorityQueue;
00137
00139 size_t id;
00140
00142 size_t numInputs;
00143
00145 size_t numOutputs;
00146
00147
00148
00150 std::vector<SimTime> inputTimes;
00151
00153 SimTime clock;
00154
00162 PriorityQueue pendingEvents;
00163
00171 bool active;
00172
00173
00177 size_t eventIdCntr;
00178
00186 void init(size_t id, size_t numOutputs, size_t numInputs) {
00187 eventIdCntr = 0;
00188 this->id = id;
00189
00190 assert (numOutputs == 1);
00191 this->numOutputs = numOutputs;
00192
00193 this->numInputs = numInputs;
00194
00195
00196 inputTimes.resize (numInputs);
00197
00198 for (size_t i = 0; i < numInputs; ++i) {
00199 inputTimes[i] = SimTime(0);
00200 }
00201
00202 pendingEvents = PriorityQueue();
00203
00204
00205 pendingEvents.reserve (numInputs * NEVENTS_PER_ITER * PQ_OVER_RESERVE);
00206
00207 clock = 0;
00208
00209 }
00210
00216 void deepCopy(const AbstractSimObject& that) {
00217
00218 init(that.id, that.numOutputs, that.numInputs);
00219
00220 for (size_t i = 0; i < numInputs; ++i) {
00221 this->inputTimes[i] = that.inputTimes[i];
00222 }
00223
00224 PriorityQueue cpyQ(that.pendingEvents);
00225 while (!cpyQ.empty ()) {
00226 this->pendingEvents.push (cpyQ.top ());
00227 cpyQ.pop ();
00228 }
00229
00230
00231 this->clock = that.clock;
00232 }
00233
00238 void updateClock() {
00239 SimTime min = INFINITY_SIM_TIME;
00240 for (size_t i = 0; i < numInputs; ++i) {
00241 if (this->inputTimes[i] < min) {
00242 min = this->inputTimes[i];
00243 }
00244 }
00245
00246 this->clock = min;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 public:
00267 AbstractSimObject(size_t id, size_t numOutputs, size_t numInputs): SimObject() {
00268 assert (numOutputs == 1);
00269 init(id, numOutputs, numInputs);
00270 }
00271
00272 AbstractSimObject (const AbstractSimObject& that): SimObject (that) {
00273 deepCopy (that);
00274 }
00275
00276 virtual ~AbstractSimObject () {}
00281 virtual AbstractSimObject* clone() const = 0;
00282
00294 EventTy makeEvent(SimObject* sendObj, SimObject* recvObj, const EventTy::Type& type, const LogicUpdate& act
00295 , const SimTime& sendTime, SimTime delay = MIN_DELAY) {
00296
00297 assert (sendObj == this);
00298
00299 if (delay <= 0) {
00300 delay = MIN_DELAY;
00301 }
00302
00303 SimTime recvTime;
00304 if (sendTime == INFINITY_SIM_TIME) {
00305 recvTime = INFINITY_SIM_TIME;
00306 } else {
00307 recvTime = sendTime + delay;
00308 }
00309 return EventTy((eventIdCntr++), sendObj, recvObj, act, type, sendTime, recvTime);
00310 }
00311
00312
00320 void recvEvent(size_t inputIndex, const EventTy& e) {
00321
00322 assert (inputIndex >= 0 && inputIndex < numInputs);
00323
00324 this->pendingEvents.push (e);
00325
00326 if (this->inputTimes[inputIndex] < e.getRecvTime()) {
00327 this->inputTimes[inputIndex] = e.getRecvTime();
00328 }
00329 }
00330
00341 virtual void execEvent(Graph& graph, GNode& myNode, const EventTy& e) = 0;
00342
00361 size_t simulate(Graph& graph, GNode& myNode) {
00362 assert (isActive ());
00363
00364 updateClock();
00365
00366 size_t retVal = 0;
00367
00368 while ((!pendingEvents.empty())
00369 && (pendingEvents.top ().getRecvTime () <= this->clock)
00370 && (retVal < NEVENTS_PER_ITER)) {
00371
00372 EventTy e = pendingEvents.top ();
00373 pendingEvents.pop ();
00374
00375
00376 if (!pendingEvents.empty ()) {
00377 const EventTy& curr = e;
00378 const EventTy& next = (pendingEvents.top ());
00379
00380
00381 if (EventRecvTimeLocalTieBrkCmp<EventTy> ().compare (curr, next) >= 0) {
00382 std::cerr << "EventRecvTimeLocalTieBrkCmp ().compare (curr, next) >= 0" << std::endl;
00383 std::cerr << "curr = " << curr.detailedString () << std::endl << "next = " << next.detailedString () << std::endl;
00384 }
00385 }
00386
00387
00388 assert (graph.getData(myNode, Galois::NONE) == this);
00389 assert (e.getRecvObj () == this);
00390
00391 execEvent(graph, myNode, e);
00392
00393 ++retVal;
00394 }
00395
00396 return (retVal);
00397 }
00398
00399
00400
00401
00407 bool isActive() const {
00408 return active;
00409 }
00410
00420 void updateActive() {
00421
00422 bool allEmpty = pendingEvents.empty ();
00423
00424 bool isWaiting = false;
00425
00426 if (allEmpty) {
00427
00428
00429
00430
00431 for (size_t i = 0; i < numInputs; ++i) {
00432 if (inputTimes[i] < INFINITY_SIM_TIME) {
00433 isWaiting = true;
00434 break;
00435 }
00436 }
00437
00438 } else {
00439
00440
00441
00442
00443
00444
00445
00446
00447 const SimTime& top = pendingEvents.top ().getRecvTime ();
00448 for (size_t i = 0; i < numInputs; ++i) {
00449 if (inputTimes[i] < top) {
00450 isWaiting = true;
00451 break;
00452 }
00453 }
00454 }
00455
00456
00457 active = !allEmpty && !isWaiting;
00458 }
00459
00460
00461 virtual size_t numPendingEvents () const {
00462 return pendingEvents.size ();
00463 }
00464
00468 virtual const std::string toString() const {
00469 std::ostringstream ss;
00470 ss << "SimObject-" << id << " ";
00471 if (DEBUG) {
00472 for (size_t i = 0; i < numInputs; ++i) {
00473 ss << ", inputTimes[" << i << "] = " << inputTimes[i];
00474 }
00475 ss << std::endl;
00476
00477 ss << ", active = " << active << ", clock = " << clock << ", pendingEvents.size() = " << pendingEvents.size ()
00478 << ", pendingEvent.top () = " << pendingEvents.top ().toString () << std::endl;
00479
00480
00481 }
00482
00483 return ss.str ();
00484 }
00485
00491 size_t getId() const { return id; }
00492
00493 };
00494
00495
00496 size_t AbstractSimObject::NEVENTS_PER_ITER = 1024;
00497 #endif