X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2Fevent_mgr.cxx;h=503bd974e7f9c551604c958787e5d191a9b09d0a;hb=f41b18f0649a50e179ba41383f4061e1878c4d4c;hp=32c499f9988961dabc906ee5900cb507a371ad22;hpb=34e2a9dc374914418d0a414490e10e1264c0a146;p=simgear.git diff --git a/simgear/structure/event_mgr.cxx b/simgear/structure/event_mgr.cxx index 32c499f9..503bd974 100644 --- a/simgear/structure/event_mgr.cxx +++ b/simgear/structure/event_mgr.cxx @@ -1,39 +1,109 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + #include "event_mgr.hxx" -void SGEventMgr::add(SGCallback* cb, +#include + +void SGEventMgr::add(const std::string& name, SGCallback* cb, double interval, double delay, bool repeat, bool simtime) { + // Clamp the delay value to 1 usec, so that user code can use + // "zero" as a synonym for "next frame". + if(delay <= 0) delay = 1e-6; + if(interval <= 0) interval = 1e-6; // No timer endless loops please... + SGTimer* t = new SGTimer; t->interval = interval; t->callback = cb; - t->mgr = this; t->repeat = repeat; - t->simtime = simtime; - + t->name = name; + t->running = false; + SGTimerQueue* q = simtime ? &_simQueue : &_rtQueue; q->insert(t, delay); } +SGTimer::~SGTimer() +{ + delete callback; + callback = NULL; +} + void SGTimer::run() { (*callback)(); +} + +SGEventMgr::SGEventMgr() : + _inited(false) +{ + +} + +SGEventMgr::~SGEventMgr() +{ + +} + +void SGEventMgr::unbind() +{ + _freezeProp.clear(); + _rtProp.clear(); +} - if(repeat) { - SGTimerQueue* q = simtime ? &mgr->_simQueue : &mgr->_rtQueue; - q->insert(this, interval); - } else { - delete callback; - delete this; +void SGEventMgr::init() +{ + if (_inited) { + SG_LOG(SG_GENERAL, SG_WARN, "duplicate init of SGEventMgr"); } + _inited = true; +} + +void SGEventMgr::shutdown() +{ + _inited = false; + + _simQueue.clear(); + _rtQueue.clear(); } void SGEventMgr::update(double delta_time_sec) { - _rtQueue.update(delta_time_sec); - if(!_freezeProp || _freezeProp->getBoolValue() == false) - _simQueue.update(delta_time_sec); + _simQueue.update(delta_time_sec); + + double rt = _rtProp ? _rtProp->getDoubleValue() : 0; + _rtQueue.update(rt); +} + +void SGEventMgr::removeTask(const std::string& name) +{ + // due to the ordering of the event-mgr in FG, tasks can be removed + // after we are shutdown (and hence, have all been cleared). Guard + // against this so we don't generate warnings below. + if (!_inited) { + return; + } + + SGTimer* t = _simQueue.findByName(name); + if (t) { + _simQueue.remove(t); + } else if ((t = _rtQueue.findByName(name))) { + _rtQueue.remove(t); + } else { + SG_LOG(SG_GENERAL, SG_WARN, "removeTask: no task found with name:" << name); + return; + } + if (t->running) { + // mark as not repeating so that the SGTimerQueue::update() + // will clean it up + t->repeat = false; + } else { + delete t; + } } //////////////////////////////////////////////////////////////////////// @@ -51,7 +121,7 @@ SGTimerQueue::SGTimerQueue(int size) _table = new HeapEntry[_tableSize]; for(int i=0; i<_tableSize; i++) { - _table[i].pri = 0; + _table[i].pri = 0; _table[i].timer = 0; } } @@ -59,22 +129,45 @@ SGTimerQueue::SGTimerQueue(int size) SGTimerQueue::~SGTimerQueue() { + clear(); delete[] _table; } +void SGTimerQueue::clear() +{ + // delete entries + for(int i=0; i<_numEntries; i++) { + delete _table[i].timer; + } + + _numEntries = 0; + + // clear entire table to empty + for(int i=0; i<_tableSize; i++) { + _table[i].pri = 0; + _table[i].timer = 0; + } +} + void SGTimerQueue::update(double deltaSecs) { _now += deltaSecs; while(_numEntries && nextTime() <= _now) { SGTimer* t = remove(); + if(t->repeat) + insert(t, t->interval); + // warning: this is not thread safe + // but the entire timer queue isn't either + t->running = true; t->run(); + t->running = false; + if (!t->repeat) + delete t; } } void SGTimerQueue::insert(SGTimer* timer, double time) { - if(time < 0) *(int*)0=0; - if(_numEntries >= _tableSize) growArray(); @@ -120,21 +213,16 @@ SGTimer* SGTimerQueue::remove() void SGTimerQueue::siftDown(int n) { - // While we have a child bigger than us: - while(((lchild(n) < (_numEntries-1)) - && (_table[n].pri < _table[lchild(n)].pri)) - || - ((rchild(n) < (_numEntries-1)) - && (_table[n].pri < _table[rchild(n)].pri))) - { - // Swap us with the biggest child - if(_table[lchild(n)].pri > _table[rchild(n)].pri) { - swap(n, lchild(n)); - n = lchild(n); - } else { - swap(n, rchild(n)); - n = rchild(n); - } + // While we have children bigger than us, swap us with the biggest + // child. + while(lchild(n) < _numEntries) { + int bigc = lchild(n); + if(rchild(n) < _numEntries && pri(rchild(n)) > pri(bigc)) + bigc = rchild(n); + if(pri(bigc) <= pri(n)) + break; + swap(n, bigc); + n = bigc; } } @@ -158,3 +246,14 @@ void SGTimerQueue::growArray() delete[] _table; _table = newTable; } + +SGTimer* SGTimerQueue::findByName(const std::string& name) const +{ + for (int i=0; i < _numEntries; ++i) { + if (_table[i].timer->name == name) { + return _table[i].timer; + } + } + + return NULL; +}