00001 #include "event_mgr.hxx"
00002
00003 void SGEventMgr::add(SGCallback* cb,
00004 double interval, double delay,
00005 bool repeat, bool simtime)
00006 {
00007
00008
00009 if(delay <= 0) delay = 0.000001;
00010
00011 SGTimer* t = new SGTimer;
00012 t->interval = interval;
00013 t->callback = cb;
00014 t->mgr = this;
00015 t->repeat = repeat;
00016 t->simtime = simtime;
00017
00018 SGTimerQueue* q = simtime ? &_simQueue : &_rtQueue;
00019
00020 q->insert(t, delay);
00021 }
00022
00023 void SGTimer::run()
00024 {
00025 (*callback)();
00026
00027 if(repeat) {
00028 SGTimerQueue* q = simtime ? &mgr->_simQueue : &mgr->_rtQueue;
00029 q->insert(this, interval);
00030 } else {
00031 delete callback;
00032 delete this;
00033 }
00034 }
00035
00036 void SGEventMgr::update(double delta_time_sec)
00037 {
00038 _simQueue.update(delta_time_sec);
00039
00040 double rt = _rtProp ? _rtProp->getDoubleValue() : 0;
00041 _rtQueue.update(rt);
00042 }
00043
00045
00046
00048
00049 SGTimerQueue::SGTimerQueue(int size)
00050 {
00051 _now = 0;
00052 _numEntries = 0;
00053 _tableSize = 1;
00054 while(size > _tableSize)
00055 _tableSize = ((_tableSize + 1)<<1) - 1;
00056
00057 _table = new HeapEntry[_tableSize];
00058 for(int i=0; i<_tableSize; i++) {
00059 _table[i].pri = 0;
00060 _table[i].timer = 0;
00061 }
00062 }
00063
00064
00065 SGTimerQueue::~SGTimerQueue()
00066 {
00067 for(int i=0; i<_numEntries; i++) {
00068 delete _table[i].timer;
00069 _table[i].timer = 0;
00070 }
00071 _numEntries = 0;
00072 delete[] _table;
00073 _table = 0;
00074 _tableSize = 0;
00075 }
00076
00077 void SGTimerQueue::update(double deltaSecs)
00078 {
00079 _now += deltaSecs;
00080 while(_numEntries && nextTime() <= _now) {
00081 SGTimer* t = remove();
00082 t->run();
00083 }
00084 }
00085
00086 void SGTimerQueue::insert(SGTimer* timer, double time)
00087 {
00088 if(_numEntries >= _tableSize)
00089 growArray();
00090
00091 _numEntries++;
00092 _table[_numEntries-1].pri = -(_now + time);
00093 _table[_numEntries-1].timer = timer;
00094
00095 siftUp(_numEntries-1);
00096 }
00097
00098 SGTimer* SGTimerQueue::remove(SGTimer* t)
00099 {
00100 int entry;
00101 for(entry=0; entry<_numEntries; entry++)
00102 if(_table[entry].timer == t)
00103 break;
00104 if(entry == _numEntries)
00105 return 0;
00106
00107
00108 swap(entry, _numEntries-1);
00109 _numEntries--;
00110 siftDown(entry);
00111
00112 return t;
00113 }
00114
00115 SGTimer* SGTimerQueue::remove()
00116 {
00117 if(_numEntries == 0) {
00118 return 0;
00119 } else if(_numEntries == 1) {
00120 _numEntries = 0;
00121 return _table[0].timer;
00122 }
00123
00124 SGTimer *result = _table[0].timer;
00125 _table[0] = _table[_numEntries - 1];
00126 _numEntries--;
00127 siftDown(0);
00128 return result;
00129 }
00130
00131 void SGTimerQueue::siftDown(int n)
00132 {
00133
00134
00135 while(lchild(n) < _numEntries) {
00136 int bigc = lchild(n);
00137 if(rchild(n) < _numEntries && pri(rchild(n)) > pri(bigc))
00138 bigc = rchild(n);
00139 if(pri(bigc) <= pri(n))
00140 break;
00141 swap(n, bigc);
00142 n = bigc;
00143 }
00144 }
00145
00146 void SGTimerQueue::siftUp(int n)
00147 {
00148 while((n != 0) && (_table[n].pri > _table[parent(n)].pri)) {
00149 swap(n, parent(n));
00150 n = parent(n);
00151 }
00152 siftDown(n);
00153 }
00154
00155 void SGTimerQueue::growArray()
00156 {
00157 _tableSize = ((_tableSize+1)<<1) - 1;
00158 HeapEntry *newTable = new HeapEntry[_tableSize];
00159 for(int i=0; i<_numEntries; i++) {
00160 newTable[i].pri = _table[i].pri;
00161 newTable[i].timer = _table[i].timer;
00162 }
00163 delete[] _table;
00164 _table = newTable;
00165 }