event_mgr.cxx

00001 #include "event_mgr.hxx"
00002 
00003 void SGEventMgr::add(SGCallback* cb,
00004                      double interval, double delay,
00005                      bool repeat, bool simtime)
00006 {
00007     // Clamp the delay value to 1 usec, so that user code can use
00008     // "zero" as a synonym for "next frame".
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 // SGTimerQueue
00046 // This is the priority queue implementation:
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     // Swap in the last item in the table, and sift down
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     // While we have children bigger than us, swap us with the biggest
00134     // child.
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 }

Generated on Mon Dec 17 09:30:54 2007 for SimGear by  doxygen 1.5.1