reSIProcate/rutil  9694
TimeLimitFifo.hxx
Go to the documentation of this file.
00001 #ifndef RESIP_TimeLimitFifo_hxx
00002 #define RESIP_TimeLimitFifo_hxx 
00003 
00004 #include <cassert>
00005 #include <memory>
00006 #include "rutil/AbstractFifo.hxx"
00007 #include <iostream>
00008 #if defined( WIN32 )
00009 #include <time.h>
00010 #endif
00011 
00012 // efficiency note: use a circular buffer to avoid list node allocation
00013 
00014 // what happens to timers that can't be queued?
00015 
00016 namespace resip
00017 {
00018 
00023 template<typename Payload>
00024 class Timestamped
00025 {
00026    public:
00027       Timestamped(const Payload& msg, time_t n)
00028          : mMsg(msg),
00029            mTime(n)
00030       {}
00031 
00032       inline const Payload& getMsg() const { return mMsg;} 
00033       inline void setMsg(const Payload& pMsg) { mMsg = pMsg;}
00034       inline const time_t& getTime() const { return mTime;} 
00035 
00036    private:
00037       Payload mMsg;
00038       time_t mTime;
00039 };
00040 
00090 template <class Msg>
00091 class TimeLimitFifo : public AbstractFifo< Timestamped<Msg*> >
00092 {
00093    public:
00094       typedef enum {EnforceTimeDepth, IgnoreTimeDepth, InternalElement} DepthUsage;
00095 
00097           TimeLimitFifo(unsigned int maxDurationSecs,
00098                     unsigned int maxSize);
00099 
00100       virtual ~TimeLimitFifo();
00101 
00102       using AbstractFifo< Timestamped<Msg*> >::mFifo;
00103       using AbstractFifo< Timestamped<Msg*> >::mMutex;
00104       using AbstractFifo< Timestamped<Msg*> >::mCondition;
00105       using AbstractFifo< Timestamped<Msg*> >::empty;
00106       using AbstractFifo< Timestamped<Msg*> >::size;
00107       using AbstractFifo< Timestamped<Msg*> >::onMessagePushed;
00108 
00128           bool add(Msg* msg, DepthUsage usage);
00129 
00140       Msg* getNext();
00151       Msg* getNext(int ms);
00152       
00157       virtual time_t timeDepth() const;
00158 
00159       
00166       bool wouldAccept(DepthUsage usage) const;
00167 
00171       void clear();
00172 
00177       virtual size_t getCountDepth() const;
00183       virtual time_t getTimeDepth() const;
00188       virtual size_t getCountDepthTolerance() const;
00193       virtual time_t getTimeDepthTolerance() const;
00201       virtual void setCountDepthTolerance(unsigned int max);
00207       virtual void setTimeDepthTolerance(unsigned int maxSecs);
00208 
00209    private:
00210       time_t timeDepthInternal() const;
00211       inline bool wouldAcceptInteral(DepthUsage usage) const;
00212       TimeLimitFifo(const TimeLimitFifo& rhs);
00213       TimeLimitFifo& operator=(const TimeLimitFifo& rhs);
00214 
00215       time_t mMaxDurationSecs;
00216       unsigned int mMaxSize;
00217       unsigned int mUnreservedMaxSize;
00218 };
00219 
00220 template <class Msg>
00221 TimeLimitFifo<Msg>::TimeLimitFifo(unsigned int maxDurationSecs,
00222                                   unsigned int maxSize)
00223    : AbstractFifo< Timestamped<Msg*> >(),
00224      mMaxDurationSecs(maxDurationSecs),
00225      mMaxSize(maxSize),
00226      mUnreservedMaxSize((int)((maxSize*8)/10)) // !dlb! random guess
00227 {}
00228 
00229 template <class Msg>
00230 TimeLimitFifo<Msg>::~TimeLimitFifo()
00231 {
00232    clear();
00233    assert(empty());
00234 }
00235 
00236 template <class Msg>
00237 bool
00238 TimeLimitFifo<Msg>::add(Msg* msg,
00239                         DepthUsage usage)
00240 {
00241    Lock lock(mMutex); (void)lock;
00242 
00243    if (wouldAcceptInteral(usage))
00244    {
00245       time_t n = time(0);
00246       mFifo.push_back(Timestamped<Msg*>(msg, n));
00247       onMessagePushed(1);
00248       mCondition.signal();
00249       return true;
00250    }
00251    else
00252    {
00253       return false;
00254    }
00255 }
00256 
00257 template <class Msg>
00258 bool
00259 TimeLimitFifo<Msg>::wouldAccept(DepthUsage usage) const
00260 {
00261    Lock lock(mMutex); (void)lock;
00262 
00263    return wouldAcceptInteral(usage);
00264 }
00265 
00266 template <class Msg>
00267 Msg*
00268 TimeLimitFifo<Msg>::getNext()
00269 {
00270    Timestamped<Msg*> tm(AbstractFifo< Timestamped<Msg*> >::getNext());
00271    return tm.getMsg();
00272 }
00273 
00274 template <class Msg>
00275 Msg*
00276 TimeLimitFifo<Msg>::getNext(int ms)
00277 {
00278    Timestamped<Msg*> tm(0,0);
00279    if(AbstractFifo< Timestamped<Msg*> >::getNext(ms, tm))
00280    {
00281       return tm.getMsg();
00282    }
00283    return 0;
00284 }
00285 
00286 template <class Msg>
00287 time_t
00288 TimeLimitFifo<Msg>::timeDepthInternal() const
00289 {
00290    if(mFifo.empty())
00291    {
00292       return 0;
00293    }
00294 
00295    return time(0) - mFifo.front().getTime();
00296 }
00297 
00298 template <class Msg>
00299 bool
00300 TimeLimitFifo<Msg>::wouldAcceptInteral(DepthUsage usage) const
00301 {
00302    if ((mMaxSize != 0 &&
00303         mFifo.size() >= mMaxSize))
00304    {
00305       return false;
00306    }
00307 
00308    if (usage == InternalElement)
00309    {
00310       return true;
00311    }
00312 
00313    if (mUnreservedMaxSize != 0 &&
00314        mFifo.size() >= mUnreservedMaxSize)
00315    {
00316       return false;
00317    }
00318 
00319    if (usage == IgnoreTimeDepth)
00320    {
00321       return true;
00322    }
00323 
00324    assert(usage == EnforceTimeDepth);
00325 
00326    if (mFifo.size() == 0 ||
00327        mMaxDurationSecs == 0 ||
00328        timeDepthInternal() < mMaxDurationSecs)
00329    {
00330       return true;
00331    }
00332 
00333    return false;
00334 }
00335 
00336 template <class Msg>
00337 time_t
00338 TimeLimitFifo<Msg>::timeDepth() const
00339 {
00340    Lock lock(mMutex); (void)lock;
00341    return timeDepthInternal();
00342 }
00343 
00344 template <class Msg>
00345 void
00346 TimeLimitFifo<Msg>::clear()
00347 {
00348    Lock lock(mMutex); (void)lock;
00349 
00350    while (!mFifo.empty())
00351    {
00352       delete mFifo.front().getMsg();
00353       mFifo.pop_front();
00354    }
00355 }
00356 
00357 template <class Msg>
00358 size_t
00359 TimeLimitFifo<Msg>::getCountDepth() const
00360 {
00361    return size();
00362 }
00363 
00364 template <class Msg>
00365 size_t
00366 TimeLimitFifo<Msg>::getCountDepthTolerance() const
00367 {
00368    return mUnreservedMaxSize;
00369 }
00370 
00371 template <class Msg>
00372 time_t 
00373 TimeLimitFifo<Msg>::getTimeDepth() const
00374 {
00375    return timeDepth();
00376 }
00377 
00378 template <class Msg>
00379 time_t
00380 TimeLimitFifo<Msg>::getTimeDepthTolerance() const
00381 {
00382    return mMaxDurationSecs;
00383 }
00384 
00385 template <class Msg>
00386 void
00387 TimeLimitFifo<Msg>::setCountDepthTolerance(unsigned int maxCount)
00388 {
00389    Lock lock(mMutex); (void)lock;
00390    mUnreservedMaxSize=int(maxCount * 0.8);
00391 }
00392 
00393 template <class Msg>
00394 void
00395 TimeLimitFifo<Msg>::setTimeDepthTolerance(unsigned int maxSecs)
00396 {
00397    Lock lock(mMutex); (void)lock;
00398 
00399    mMaxDurationSecs=maxSecs;
00400 }
00401 
00402 
00403 } // namespace resip
00404 
00405 #endif
00406 
00407 /* ====================================================================
00408  * The Vovida Software License, Version 1.0 
00409  * 
00410  * Redistribution and use in source and binary forms, with or without
00411  * modification, are permitted provided that the following conditions
00412  * are met:
00413  * 
00414  * 1. Redistributions of source code must retain the above copyright
00415  *    notice, this list of conditions and the following disclaimer.
00416  * 
00417  * 2. Redistributions in binary form must reproduce the above copyright
00418  *    notice, this list of conditions and the following disclaimer in
00419  *    the documentation and/or other materials provided with the
00420  *    distribution.
00421  * 
00422  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00423  *    and "Vovida Open Communication Application Library (VOCAL)" must
00424  *    not be used to endorse or promote products derived from this
00425  *    software without prior written permission. For written
00426  *    permission, please contact vocal@vovida.org.
00427  *
00428  * 4. Products derived from this software may not be called "VOCAL", nor
00429  *    may "VOCAL" appear in their name, without prior written
00430  *    permission of Vovida Networks, Inc.
00431  * 
00432  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00433  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00434  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00435  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00436  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00437  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00438  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00439  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00440  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00441  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00442  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00443  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00444  * DAMAGE.
00445  * 
00446  * ====================================================================
00447  * 
00448  * This software consists of voluntary contributions made by Vovida
00449  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00450  * Inc.  For more information on Vovida Networks, Inc., please see
00451  * <http://www.vovida.org/>.
00452  *
00453  */