reSIProcate/stack  9694
CancelableTimerQueue.hxx
Go to the documentation of this file.
00001 #ifndef resip_CancelableTimerQueue_hxx
00002 #define resip_CancelableTimerQueue_hxx
00003 
00004 #include <map>
00005 #include <limits.h>
00006 #include <iosfwd>
00007 
00008 #include "rutil/Timer.hxx"
00009 #include "rutil/HashMap.hxx"
00010 #include "rutil/Inserter.hxx"
00011 
00012 using namespace std;
00013 
00014 namespace resip
00015 {
00016 
00017 template<class T>
00018 class CancelableTimerQueue
00019 {
00020     public:
00021       CancelableTimerQueue() : mNextId(0) {};
00022       ~CancelableTimerQueue() {};
00023 
00024       typedef long Id;
00025    private:
00026       typedef std::multimap< UInt64, std::pair<T, Id> > TimerMap;
00027       typedef HashMap<Id, UInt64> IdToTimer;
00028 
00029    public:
00030       Id addRelative(T msg,
00031                      unsigned int offset)
00032       {
00033          return addTimer(msg, resip::Timer::getTimeMs() + offset);
00034       }
00035 
00036       //returns true if the id existed
00037       bool cancel(Id id)
00038       {
00039          typename IdToTimer::iterator j = mIdToTimer.find(id);
00040          if (j == mIdToTimer.end())
00041          {
00042             return false;
00043          }
00044          
00045          for (typename TimerMap::iterator i = mTimerMap.lower_bound(j->second); i != mTimerMap.upper_bound(j->second); i++)
00046          {
00047             if (i->second.second == id)
00048             {
00049                mTimerMap.erase(i);
00050                mIdToTimer.erase(j);
00051                return true;
00052             }
00053          }
00054          //cerr << "mIdToTimer: " << Inserter(mIdToTimer) << endl;
00055          //cerr << "Searching for ID: " << id << endl;
00056          //cerr << "TimerMap state: " << Inserter(mTimerMap) << endl;
00057          assert(mIdToTimer.size() == mTimerMap.size());
00058          assert(0);
00059       }
00060 
00061       //get the number of milliseconds until the next event, returns -1 if no
00062       //event is available
00063       int getTimeout() const
00064       {
00065          if (mTimerMap.empty())
00066          {
00067             return -1;
00068          }
00069          else
00070          {
00071             if (mTimerMap.begin()->first - resip::Timer::getTimeMs() < 0)
00072             {
00073                return 0;
00074             }
00075             else
00076             {
00077                return mTimerMap.begin()->first - resip::Timer::getTimeMs();
00078             }
00079          }
00080       }
00081          
00082       bool available() const
00083       {
00084          return (!mTimerMap.empty() && 
00085                  mTimerMap.begin()->first <= resip::Timer::getTimeMs());
00086       }
00087 
00088       T getNext()
00089       {
00090          assert(mIdToTimer.size() == mTimerMap.size());
00091 
00092          assert(available());
00093 
00094          typename TimerMap::iterator it = mTimerMap.begin();
00095          mIdToTimer.erase(it->second.second);
00096 
00097          T msg = it->second.first;
00098          mTimerMap.erase(it);
00099 
00100          assert(mIdToTimer.size() == mTimerMap.size());
00101          
00102          return msg;
00103       }
00104 
00105       void clear()
00106       {
00107          mTimerMap.clear();
00108          mIdToTimer.clear();
00109       }
00110 
00111       bool empty() const
00112       {
00113          return mTimerMap.empty();
00114       }
00115 
00116       size_t size() const
00117       {
00118          return mTimerMap.size();
00119       }
00120 
00121    private:
00122       
00123       Id addTimer(T msg, UInt64 expiry)
00124       {
00125          Id id = getNextId();
00126          mTimerMap.insert(std::make_pair(expiry, std::make_pair(msg, id)));
00127          mIdToTimer[id] = expiry;
00128          assert(mIdToTimer.size() == mTimerMap.size());
00129          return id;
00130       }
00131 
00132       Id getNextId()
00133       {
00134          mNextId++;
00135          if (mNextId == INT_MAX)
00136          {
00137             mNextId = 1;
00138          }
00139          return mNextId;
00140       }
00141          
00142       Id mNextId;
00143       IdToTimer mIdToTimer;
00144       TimerMap mTimerMap;
00145 };
00146 
00147 }
00148 
00149 #endif
00150 /* ====================================================================
00151  * The Vovida Software License, Version 1.0 
00152  * 
00153  * Copyright (c) 2004 PurpleComm, Inc.  All rights reserved.
00154  * 
00155  * Redistribution and use in source and binary forms, with or without
00156  * modification, are permitted provided that the following conditions
00157  * are met:
00158  * 
00159  * 1. Redistributions of source code must retain the above copyright
00160  *    notice, this list of conditions and the following disclaimer.
00161  * 
00162  * 2. Redistributions in binary form must reproduce the above copyright
00163  *    notice, this list of conditions and the following disclaimer in
00164  *    the documentation and/or other materials provided with the
00165  *    distribution.
00166  * 
00167  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00168  *    and "Vovida Open Communication Application Library (VOCAL)" must
00169  *    not be used to endorse or promote products derived from this
00170  *    software without prior written permission. For written
00171  *    permission, please contact vocal@vovida.org.
00172  *
00173  * 4. Products derived from this software may not be called "VOCAL", nor
00174  *    may "VOCAL" appear in their name, without prior written
00175  *    permission of Vovida Networks, Inc.
00176  * 
00177  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00178  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00179  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00180  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00181  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00182  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00183  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00184  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00185  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00186  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00187  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00188  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00189  * DAMAGE.
00190  * 
00191  */