📄 delayqueue.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// Copyright (c) 1996-2000, Live Networks, Inc. All rights reserved// Help by Carlo Bonamico to get working for Windows// Delay queue// Implementation#include "DelayQueue.hh"#include "GroupsockHelper.hh"static const int MILLION = 1000000;///// Timeval /////int Timeval::operator>=(const Timeval& arg2) const { return seconds() > arg2.seconds() || (seconds() == arg2.seconds() && useconds() >= arg2.useconds());}void Timeval::operator+=(const DelayInterval& arg2) { secs() += arg2.seconds(); usecs() += arg2.useconds(); if (usecs() >= MILLION) { usecs() -= MILLION; ++secs(); }}void Timeval::operator-=(const DelayInterval& arg2) { secs() -= arg2.seconds(); usecs() -= arg2.useconds(); if (usecs() < 0) { usecs() += MILLION; --secs(); } if (secs() < 0) secs() = usecs() = 0;}DelayInterval operator-(const Timeval& arg1, const Timeval& arg2) { time_base_seconds secs = arg1.seconds() - arg2.seconds(); time_base_seconds usecs = arg1.useconds() - arg2.useconds(); if (usecs < 0) { usecs += MILLION; --secs; } if (secs < 0) return ZERO; else return DelayInterval(secs, usecs);}///// DelayInterval /////DelayInterval operator*(short arg1, const DelayInterval& arg2) { time_base_seconds result_seconds = arg1*arg2.seconds(); time_base_seconds result_useconds = arg1*arg2.useconds(); time_base_seconds carry = result_useconds/MILLION; result_useconds -= carry*MILLION; result_seconds += carry; return DelayInterval(result_seconds, result_useconds);}#ifndef INT_MAX#define INT_MAX 0x7FFFFFFF#endifconst DelayInterval ZERO(0, 0);const DelayInterval SECOND(1, 0);const DelayInterval ETERNITY(INT_MAX, MILLION-1);// used internally to make the implementation work///// DelayQueueEntry /////long DelayQueueEntry::tokenCounter = 0;DelayQueueEntry::DelayQueueEntry(DelayInterval delay) : fDeltaTimeRemaining(delay) { fNext = fPrev = this; fToken = ++tokenCounter;}DelayQueueEntry::~DelayQueueEntry() {}void DelayQueueEntry::handleTimeout() { delete this;}///// DelayQueue /////DelayQueue::DelayQueue() : DelayQueueEntry(ETERNITY) { fLastSyncTime = TimeNow();}DelayQueue::~DelayQueue() { while (fNext != this) removeEntry(fNext);}void DelayQueue::addEntry(DelayQueueEntry* newEntry) { synchronize(); DelayQueueEntry* cur = head(); while (newEntry->fDeltaTimeRemaining >= cur->fDeltaTimeRemaining) { newEntry->fDeltaTimeRemaining -= cur->fDeltaTimeRemaining; cur = cur->fNext; } cur->fDeltaTimeRemaining -= newEntry->fDeltaTimeRemaining; // Add "newEntry" to the queue, just before "cur": newEntry->fNext = cur; newEntry->fPrev = cur->fPrev; cur->fPrev = newEntry->fPrev->fNext = newEntry;}void DelayQueue::updateEntry(DelayQueueEntry* entry, DelayInterval newDelay) { if (entry == NULL) return; removeEntry(entry); entry->fDeltaTimeRemaining = newDelay; addEntry(entry);}void DelayQueue::updateEntry(long tokenToFind, DelayInterval newDelay) { DelayQueueEntry* entry = findEntryByToken(tokenToFind); updateEntry(entry, newDelay);}void DelayQueue::removeEntry(DelayQueueEntry* entry) { if (entry == NULL || entry->fNext == NULL) return; entry->fNext->fDeltaTimeRemaining += entry->fDeltaTimeRemaining; entry->fPrev->fNext = entry->fNext; entry->fNext->fPrev = entry->fPrev; entry->fNext = entry->fPrev = NULL; // in case we should try to remove it again}DelayQueueEntry* DelayQueue::removeEntry(long tokenToFind) { DelayQueueEntry* entry = findEntryByToken(tokenToFind); removeEntry(entry); return entry;}DelayInterval const& DelayQueue::timeToNextAlarm() { if (head()->fDeltaTimeRemaining == ZERO) return ZERO; // a common case synchronize(); return head()->fDeltaTimeRemaining;}void DelayQueue::handleAlarm() { if (head()->fDeltaTimeRemaining != ZERO) synchronize(); if (head()->fDeltaTimeRemaining == ZERO) { // This event is due to be handled: DelayQueueEntry* toRemove = head(); removeEntry(toRemove); // do this first, in case handler accesses queue toRemove->handleTimeout(); }}DelayQueueEntry* DelayQueue::findEntryByToken(long tokenToFind) { DelayQueueEntry* cur = head(); while (cur != this) { if (cur->token() == tokenToFind) return cur; cur = cur->fNext; } return NULL;}void DelayQueue::synchronize() { // First, figure out how much time has elapsed since the last sync: EventTime timeNow = TimeNow(); DelayInterval timeSinceLastSync = timeNow - fLastSyncTime; fLastSyncTime = timeNow; // Then, adjust the delay queue for any entries whose time is up: DelayQueueEntry* curEntry = head(); while (timeSinceLastSync >= curEntry->fDeltaTimeRemaining) { timeSinceLastSync -= curEntry->fDeltaTimeRemaining; curEntry->fDeltaTimeRemaining = ZERO; curEntry = curEntry->fNext; } curEntry->fDeltaTimeRemaining -= timeSinceLastSync;}///// EventTime /////EventTime TimeNow() { struct timeval tvNow; gettimeofday(&tvNow, NULL); return EventTime(tvNow.tv_sec, tvNow.tv_usec);}DelayInterval TimeRemainingUntil(const EventTime& futureEvent) { return futureEvent - TimeNow();}const EventTime THE_END_OF_TIME(INT_MAX);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -