/********** This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. (See .) This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // Copyright (c) 1996-2015, Live Networks, Inc. All rights reserved // Delay queue // C++ header #ifndef _DELAY_QUEUE_HH #define _DELAY_QUEUE_HH #ifndef _NET_COMMON_H #include "NetCommon.h" #endif #ifdef TIME_BASE typedef TIME_BASE time_base_seconds; #else typedef long time_base_seconds; #endif ///// A "Timeval" can be either an absolute time, or a time interval ///// class Timeval { public: time_base_seconds seconds() const { return fTv.tv_sec; } time_base_seconds seconds() { return fTv.tv_sec; } time_base_seconds useconds() const { return fTv.tv_usec; } time_base_seconds useconds() { return fTv.tv_usec; } int operator>=(Timeval const& arg2) const; int operator<=(Timeval const& arg2) const { return arg2 >= *this; } int operator<(Timeval const& arg2) const { return !(*this >= arg2); } int operator>(Timeval const& arg2) const { return arg2 < *this; } int operator==(Timeval const& arg2) const { return *this >= arg2 && arg2 >= *this; } int operator!=(Timeval const& arg2) const { return !(*this == arg2); } void operator+=(class DelayInterval const& arg2); void operator-=(class DelayInterval const& arg2); // returns ZERO iff arg2 >= arg1 protected: Timeval(time_base_seconds seconds, time_base_seconds useconds) { fTv.tv_sec = seconds; fTv.tv_usec = useconds; } private: time_base_seconds& secs() { return (time_base_seconds&)fTv.tv_sec; } time_base_seconds& usecs() { return (time_base_seconds&)fTv.tv_usec; } struct timeval fTv; }; #ifndef max inline Timeval max(Timeval const& arg1, Timeval const& arg2) { return arg1 >= arg2 ? arg1 : arg2; } #endif #ifndef min inline Timeval min(Timeval const& arg1, Timeval const& arg2) { return arg1 <= arg2 ? arg1 : arg2; } #endif class DelayInterval operator-(Timeval const& arg1, Timeval const& arg2); // returns ZERO iff arg2 >= arg1 ///// DelayInterval ///// class DelayInterval: public Timeval { public: DelayInterval(time_base_seconds seconds, time_base_seconds useconds) : Timeval(seconds, useconds) {} }; DelayInterval operator*(short arg1, DelayInterval const& arg2); extern DelayInterval const DELAY_ZERO; extern DelayInterval const DELAY_SECOND; extern DelayInterval const DELAY_MINUTE; extern DelayInterval const DELAY_HOUR; extern DelayInterval const DELAY_DAY; ///// _EventTime ///// class _EventTime: public Timeval { public: _EventTime(unsigned secondsSinceEpoch = 0, unsigned usecondsSinceEpoch = 0) // We use the Unix standard epoch: January 1, 1970 : Timeval(secondsSinceEpoch, usecondsSinceEpoch) {} }; _EventTime TimeNow(); extern _EventTime const THE_END_OF_TIME; ///// DelayQueueEntry ///// class DelayQueueEntry { public: virtual ~DelayQueueEntry(); intptr_t token() { return fToken; } protected: // abstract base class DelayQueueEntry(DelayInterval delay); virtual void handleTimeout(); private: friend class DelayQueue; DelayQueueEntry* fNext; DelayQueueEntry* fPrev; DelayInterval fDeltaTimeRemaining; intptr_t fToken; static intptr_t tokenCounter; }; ///// DelayQueue ///// class DelayQueue: public DelayQueueEntry { public: DelayQueue(); virtual ~DelayQueue(); void addEntry(DelayQueueEntry* newEntry); // returns a token for the entry void updateEntry(DelayQueueEntry* entry, DelayInterval newDelay); void updateEntry(intptr_t tokenToFind, DelayInterval newDelay); void removeEntry(DelayQueueEntry* entry); // but doesn't delete it DelayQueueEntry* removeEntry(intptr_t tokenToFind); // but doesn't delete it DelayInterval const& timeToNextAlarm(); void handleAlarm(); private: DelayQueueEntry* head() { return fNext; } DelayQueueEntry* findEntryByToken(intptr_t token); void synchronize(); // bring the 'time remaining' fields up-to-date _EventTime fLastSyncTime; }; #endif