/** * This function calls any script timers which have expired by now */ void tick( double timeNow ) { const int MAX_TIMER_CALLS_PER_FRAME = 1000; Timers timersToCall; Timers::iterator iter = gTimers.begin(); while ( iter != gTimers.end() ) { if ( iter->time <= timeNow ) { timersToCall.push_back( *iter ); iter = gTimers.erase( iter ); } else { ++iter; } } // Using a reverse iterator, since the TimerRecord comparison operator causes // the sorted list to be in reverse order (earlier timers are later in the list). stable_sort( timersToCall.begin(), timersToCall.end() ); int numExpired = 0; Timers::reverse_iterator revIter = timersToCall.rbegin(); for ( ; revIter != timersToCall.rend() && numExpired < MAX_TIMER_CALLS_PER_FRAME; ++revIter ) { TimerRecord& timer = *revIter; gFreeTimerHandles.push( timer.handle ); Script::call( timer.function, timer.arguments, timer.source ); // Script::call decrefs timer.function and timer.arguments for us numExpired++; } if (numExpired >= MAX_TIMER_CALLS_PER_FRAME) { // If there are too many to run this frame, put the remainder back into the main list. for ( ; revIter != timersToCall.rend(); ++revIter ) { TimerRecord& timer = *revIter; gTimers.push_back( timer ); } //ERROR_MSG( "BigWorldClientScript::tick: Loop interrupted because" // " too many timers (> %d) wanted to expire this frame!", // numExpired ); } }
void Timer::pollTimers() { // Generate messages for timers if (!timers.empty()) { int t = ji_clock; int count; for (Timers::iterator it=timers.begin(), end=timers.end(); it != end; ++it) { Timer* timer = *it; if (timer && timer->m_lastTime >= 0) { count = 0; while (t - timer->m_lastTime > timer->m_interval) { timer->m_lastTime += timer->m_interval; ++count; /* we spend too much time here */ if (ji_clock - t > timer->m_interval) { timer->m_lastTime = ji_clock; break; } } if (count > 0) { ASSERT(timer->m_owner != NULL); Message* msg = new TimerMessage(count, timer); msg->addRecipient(timer->m_owner); Manager::getDefault()->enqueueMessage(msg); } } } } }
Timer::~Timer() { Timers::iterator it = std::find(timers.begin(), timers.end(), this); ASSERT(it != timers.end()); timers.erase(it); // Remove messages of this timer in the queue Manager::getDefault()->removeMessagesForTimer(this); }
/** * Clears and releases all existing timers. */ void clearTimers() { // this has to be called at a different time // than fini, that's why it's a separate method for( Timers::iterator iTimer = gTimers.begin(); iTimer != gTimers.end(); iTimer++ ) { Py_DECREF( iTimer->function ); Py_DECREF( iTimer->arguments ); } gTimers.clear(); }
Timer::~Timer() { assert_ui_thread(); auto it = std::find(timers.begin(), timers.end(), this); ASSERT(it != timers.end()); if (it != timers.end()) timers.erase(it); // Stop the timer and remove it from the message queue. stop(); }