/********** 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 3 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-2019, 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