#include "common/dispatcher.h" #include #if (USE_XF_COMMON_TIMEOUTMANAGER_CLASS != 0) #include #include "xf/interface/behavior.h" #include "xf/interface/mutex.h" #include "timeoutmanager.h" #if defined(XF_TRACE_EVENT_PUSH_POP) && (XF_TRACE_EVENT_PUSH_POP != 0) #include "trace/trace.h" #endif // XF_TRACE_EVENT_PUSH_POP using Mutex = interface::XFMutex; // Rename XFMutex interface class to Mutex for easier use. // Implementation of the getInstance() method of the 'interface::XFTimeoutManager' class. // // Note: The implementation is done here because only in this file the real XFTimeoutManager // class is known (port specific class). An instance of the XFTimeoutManager class is // returned by the 'interface::XFTimeoutManager' class. interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance() { static ::XFTimeoutManager timeoutManager; return &timeoutManager; } XFTimeoutManager::XFTimeoutManager() { this->pMutex_ = interface::XFMutex::create(); } XFTimeoutManager::~XFTimeoutManager() { } void XFTimeoutManager::addTimeout(XFTimeout *pNewTimeout) { const int desireInterval = pNewTimeout->getInterval(); int intervalOfTimeout = 0; int ticks; this->pMutex_->lock(); if(this->timeouts_.empty()) { ticks = (desireInterval-intervalOfTimeout); if(ticks<=0) ticks = 0; pNewTimeout->setRelTicks(ticks); this->timeouts_.push_back(pNewTimeout); this->pMutex_->unlock(); return; } TimeoutList::iterator it = this->timeouts_.begin(); while(intervalOfTimeout < desireInterval) { if(++it == this->timeouts_.end()){ ticks = (desireInterval-intervalOfTimeout); if(ticks<=0) ticks = 0; pNewTimeout->setRelTicks(ticks); this->timeouts_.push_back(pNewTimeout); this->pMutex_->unlock(); return; } else { intervalOfTimeout += (*it)->getRelTicks(); } } if(intervalOfTimeout == desireInterval) { if(++it == this->timeouts_.end()) { ticks = (desireInterval-intervalOfTimeout); if(ticks<=0) ticks = 0; pNewTimeout->setRelTicks(ticks); this->timeouts_.push_back(pNewTimeout); this->pMutex_->unlock(); return; } else { while((*it)->getRelTicks() == 0) { if(++it == this->timeouts_.end()) { ticks = (desireInterval-intervalOfTimeout); if(ticks<=0) ticks = 0; pNewTimeout->setRelTicks(ticks); this->timeouts_.push_back(pNewTimeout); this->pMutex_->unlock(); return; } it++; } } } // TODO change for take care of 10ms ecart of timeout ticks = (desireInterval-intervalOfTimeout); ticks = ticks > 0 ? ticks/this->tickInterval_ : 0; (*it)->substractFromRelTicks(ticks); pNewTimeout->setRelTicks(ticks); this->timeouts_.insert(--it, pNewTimeout); this->pMutex_->unlock(); return; } void XFTimeoutManager::returnTimeout(XFTimeout *pTimeout) { this->pMutex_->lock(); XFDispatcher::getInstance()->pushEvent(pTimeout); this->timeouts_.remove(pTimeout); this->pMutex_->unlock(); } void XFTimeoutManager::start(std::function startTimeoutManagerTimer) { startTimeoutManagerTimer(this->tickInterval_); } void XFTimeoutManager::scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFBehavior *pBehavior) { ::XFTimeout* timeout = new XFTimeout(timeoutId, interval, pBehavior); addTimeout(timeout); } void XFTimeoutManager::unscheduleTimeout(int32_t timeoutId, interface::XFBehavior *pBehavior) { this->pMutex_->lock(); TimeoutList::iterator it; for(it = this->timeouts_.begin(); it != this->timeouts_.end(); it++){ if((*it)->getId()==timeoutId && (*it)->getBehavior() == pBehavior) { it = this->timeouts_.erase(it); } } this->pMutex_->unlock(); } void XFTimeoutManager::tick() { if(!this->timeouts_.empty()) { this->pMutex_->lock(); XFTimeout* timeout = this->timeouts_.front(); timeout->substractFromRelTicks(tickInterval_); while (timeout->getRelTicks() <= 0 ) { XFDispatcher::getInstance()->pushEvent(timeout); this->timeouts_.pop_front(); timeout = this->timeouts_.front(); } this->pMutex_->unlock(); } } #endif // USE_XF_COMMON_TIMEOUTMANAGER_CLASS