reSIProcate/rutil  9694
GenericTimerQueue.hxx
Go to the documentation of this file.
00001 #ifndef RUTIL_GENERICTIMERQUEUE_HXX
00002 #define RUTIL_GENERICTIMERQUEUE_HXX
00003 
00004 #include "rutil/Timer.hxx"
00005 #include <set>
00006 #include <vector>
00007 
00008 namespace resip {
00009 
00010 // !dcm! -- hoist?
00011 template<class T>
00012 class GenericTimerQueue
00013 {
00014    public:
00015 
00016       // !dcm! -- can def. hoist
00017       template<class E>
00018       class TimerEntry
00019       {
00020          public:
00021             TimerEntry(unsigned long tms, E* event) :
00022                mWhen(tms + Timer::getTimeMs()),
00023                mEvent(event)
00024             {
00025             }
00026             
00027             E* getEvent() const
00028             {
00029                return mEvent;
00030             }
00031             
00032             bool operator<(const TimerEntry<E>& rhs) const
00033             {
00034                return mWhen < rhs.mWhen;
00035             }
00036             UInt64 mWhen;
00037             E* mEvent;
00038       };
00039            
00041       virtual ~GenericTimerQueue()
00042       {
00043          for (typename std::multiset<TimerEntry<T> >::iterator i = mTimers.begin(); i !=  mTimers.end(); ++i)
00044          {
00045             delete i->mEvent;            
00046          }
00047       }
00048       
00049       virtual void process()
00050       {
00051          if (!mTimers.empty() && msTillNextTimer() == 0)
00052          {
00053             TimerEntry<T> now(0, 0);
00054 
00055             // hacky solution, needs work, insertion from processTimer
00056             // caused bizarre infinite loop issues in previous revision;
00057             // this code is in desperate need of help
00058             typedef typename std::multiset<TimerEntry<T> > TimerSet;
00059             typedef std::vector<typename TimerSet::iterator> ItVector;
00060             ItVector iterators;
00061 
00062             typename TimerSet::iterator end = mTimers.upper_bound(now);
00063             typename TimerSet::iterator begin = mTimers.begin();
00064 
00065             for (typename TimerSet::iterator i = begin; i != end; ++i)
00066             {
00067                iterators.push_back(i);
00068             }
00069 
00070             for (typename ItVector::iterator i = iterators.begin(); i != iterators.end(); ++i)
00071             {
00072                assert((*i)->getEvent());
00073                processTimer((*i)->getEvent());               
00074             }
00075 
00077             for (typename ItVector::iterator i = iterators.begin(); i != iterators.end(); ++i)
00078             {
00079                mTimers.erase(*i);
00080             }
00081          }
00082       }
00083 
00084       virtual void processTimer(T*)=0;      
00085 
00086           void add(T* event, unsigned long msOffset)
00087           {
00088               TimerEntry<T> t(msOffset, event);
00089                   mTimers.insert(t);
00090           }
00091 
00092       int size() const
00093       {
00094          return mTimers.size();
00095       }
00096       
00097       bool empty() const
00098       {
00099          return mTimers.empty();
00100       }
00101       
00102       unsigned int msTillNextTimer()
00103       {
00104          if (!mTimers.empty())
00105          {
00106             UInt64 next = mTimers.begin()->mWhen;
00107             UInt64 now = Timer::getTimeMs();
00108             if (now > next) 
00109             {
00110                return 0;
00111             }
00112             else
00113             {
00114                UInt64 ret64 = next - now;
00115                if ( ret64 > UInt64(INT_MAX) )
00116                {
00117                   return INT_MAX;
00118                }
00119                else
00120                { 
00121                   int ret = int(ret64);
00122                   return ret;
00123                }
00124             }
00125          }
00126          else
00127          {
00128             return INT_MAX;
00129          }
00130       }
00131 
00132       
00133    protected:
00134 //      friend std::ostream& operator<<(std::ostream&, const GenericTimerQueue&);
00135       std::multiset<TimerEntry<T> > mTimers;
00136 };
00137 
00138 }
00139 
00140 #endif // RUTIL_GENERICTIMERQUEUE_HXX