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