|
reSIProcate/rutil
9694
|
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 */
1.7.5.1