reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
AbstractFifo.hxx
Go to the documentation of this file.
1#ifndef RESIP_AbstractFifo_hxx
2#define RESIP_AbstractFifo_hxx
3
4#include "rutil/ResipAssert.h"
5#include <deque>
6
7#include "rutil/Mutex.hxx"
8#include "rutil/Condition.hxx"
9#include "rutil/Lock.hxx"
11
12#include "rutil/compat.hxx"
13#include "rutil/Timer.hxx"
14
15namespace resip
16{
30{
31 public:
32
34 virtual ~FifoStatsInterface();
35
40 virtual time_t expectedWaitTimeMilliSec() const =0;
41
46 virtual time_t getTimeDepth() const = 0;
47
51 virtual size_t getCountDepth() const = 0;
52
57 virtual time_t averageServiceTimeMicroSec() const = 0;
58
69 inline uint8_t getRole() const {return mRole;}
70
76 inline void setRole(uint8_t role) {mRole=role;}
77
84 inline void setDescription(const resip::Data& description)
85 {
86 mDescription=description;
87 }
88
93 virtual const resip::Data& getDescription() const {return mDescription;}
94
95 protected:
98};
99
110#define RESIP_FIFO_NOWAIT -1
111#define RESIP_FIFO_FOREVER 0
112
124template <typename T>
126{
127 public:
139
141 {
142 }
143
148 bool empty() const
149 {
150 Lock lock(mMutex); (void)lock;
151 return mFifo.empty();
152 }
153
161 virtual unsigned int size() const
162 {
163 Lock lock(mMutex); (void)lock;
164 return (unsigned int)mFifo.size();
165 }
166
172 bool messageAvailable() const
173 {
174 Lock lock(mMutex); (void)lock;
175 return !mFifo.empty();
176 }
177
183 virtual time_t getTimeDepth() const
184 {
185 return 0;
186 }
187
188 virtual size_t getCountDepth() const
189 {
190 return mSize;
191 }
192
193 virtual time_t expectedWaitTimeMilliSec() const
194 {
195 return ((mAverageServiceTimeMicroSec*mSize)+500)/1000;
196 }
197
198 virtual time_t averageServiceTimeMicroSec() const
199 {
201 }
202
204 virtual void clear() {};
205
206 protected:
217 {
218 Lock lock(mMutex); (void)lock;
219 onFifoPolled();
220
221 // Wait util there are messages available.
222 while (mFifo.empty())
223 {
224 mCondition.wait(lock);
225 }
226
227 // Return the first message on the fifo.
228 //
229 T firstMessage(mFifo.front());
230 mFifo.pop_front();
232 return firstMessage;
233 }
234
235
245 bool getNext(int ms, T& toReturn)
246 {
247 if(ms == 0)
248 {
249 toReturn = getNext();
250 return true;
251 }
252
253 if(ms < 0)
254 {
255 Lock lock(mMutex); (void)lock;
256 onFifoPolled();
257 if (mFifo.empty()) // WATCHOUT: Do not test mSize instead
258 return false;
259 toReturn = mFifo.front();
260 mFifo.pop_front();
262 return true;
263 }
264
265 const auto begin = std::chrono::steady_clock::now();
266 const auto end = begin + std::chrono::milliseconds(ms);
267 Lock lock(mMutex); (void)lock;
268 onFifoPolled();
269
270 // Wait until there are messages available
271 while (mFifo.empty())
272 {
273 if(ms==0)
274 {
275 return false;
276 }
277 auto now = std::chrono::steady_clock::now();
278 if(now >= end)
279 {
280 return false;
281 }
282
283 // bail if total wait time exceeds limit
284 bool signaled = mCondition.wait_until(lock, end) == std::cv_status::no_timeout;
285 if (!signaled)
286 {
287 return false;
288 }
289 }
290
291 // Return the first message on the fifo.
292 //
293 toReturn=mFifo.front();
294 mFifo.pop_front();
296 return true;
297 }
298
299 typedef std::deque<T> Messages;
300
301 void getMultiple(Messages& other, unsigned int max)
302 {
303 Lock lock(mMutex); (void)lock;
304 onFifoPolled();
305 resip_assert(other.empty());
306 while (mFifo.empty())
307 {
308 mCondition.wait(lock);
309 }
310
311 if(mFifo.size() <= max)
312 {
313 std::swap(mFifo, other);
315 }
316 else
317 {
318 size_t num=max;
319 while( 0 != max-- )
320 {
321 other.push_back(mFifo.front());
322 mFifo.pop_front();
323 }
324 onMessagePopped((unsigned int)num);
325 }
326 }
327
328 bool getMultiple(int ms, Messages& other, unsigned int max)
329 {
330 if(ms==0)
331 {
332 getMultiple(other,max);
333 return true;
334 }
335
336 resip_assert(other.empty());
337 const auto begin = std::chrono::steady_clock::now();
338 const auto end = begin + std::chrono::milliseconds(ms); // !kh! ms should've been unsigned :(
339 Lock lock(mMutex); (void)lock;
340 onFifoPolled();
341
342 // Wait until there are messages available
343 while (mFifo.empty())
344 {
345 if(ms < 0)
346 {
347 return false;
348 }
349 const auto now = std::chrono::steady_clock::now();
350 if(now >= end)
351 {
352 return false;
353 }
354
355 // bail if total wait time exceeds limit
356 bool signaled = mCondition.wait_until(lock, end) == std::cv_status::no_timeout;
357 if (!signaled)
358 {
359 return false;
360 }
361 }
362
363 if(mFifo.size() <= max)
364 {
365 std::swap(mFifo, other);
367 }
368 else
369 {
370 size_t num=max;
371 while( 0 != max-- )
372 {
373 other.push_back(mFifo.front());
374 mFifo.pop_front();
375 }
376 onMessagePopped((unsigned int)num);
377 }
378 return true;
379 }
380
381 size_t add(const T& item)
382 {
383 Lock lock(mMutex); (void)lock;
384 mFifo.push_back(item);
385 mCondition.notify_one();
387 return mFifo.size();
388 }
389
390 size_t addMultiple(Messages& items)
391 {
392 Lock lock(mMutex); (void)lock;
393 size_t size=items.size();
394 if(mFifo.empty())
395 {
396 std::swap(mFifo, items);
397 }
398 else
399 {
400 // I suppose it is possible to optimize this as a push_front() from
401 // mFifo to items, and then do a swap, if items is larger.
402 while(!items.empty())
403 {
404 mFifo.push_back(items.front());
405 items.pop_front();
406 }
407 }
408 mCondition.notify_one();
409 onMessagePushed((int)size);
410 return mFifo.size();
411 }
412
416 mutable Mutex mMutex;
419
423 // std::deque has to perform some amount of traversal to calculate its
424 // size; we maintain this count so that it can be queried without locking,
425 // in situations where it being off by a small amount is ok.
427
428 virtual void onFifoPolled()
429 {
430 // !bwc! TODO allow this sampling frequency to be tweaked
432 mCounter &&
433 (mCounter >= 64 || mFifo.empty()))
434 {
437
438 if(mCounter >= 4096)
439 {
441 }
442 else // fifo got emptied; merge into a rolling average
443 {
444 // .bwc. This is a moving average with period 64, round to
445 // nearest int.
448 4096U);
449 }
450 mCounter=0;
451 if(mFifo.empty())
452 {
454 }
455 else
456 {
458 }
459 }
460 }
461
466 virtual void onMessagePopped(unsigned int num=1)
467 {
468 mCounter+=num;
469 mSize-=num;
470 }
471
472 virtual void onMessagePushed(int num)
473 {
474 if(mSize==0)
475 {
476 // Fifo went from empty to non-empty. Take a timestamp, and record
477 // how long it takes to process some messages.
479 }
480 mSize+=num;
481 }
482 private:
483 // no value semantics
485 AbstractFifo& operator=(const AbstractFifo&);
486};
487
488} // namespace resip
489
490#endif
491
492/* ====================================================================
493 * The Vovida Software License, Version 1.0
494 *
495 * Redistribution and use in source and binary forms, with or without
496 * modification, are permitted provided that the following conditions
497 * are met:
498 *
499 * 1. Redistributions of source code must retain the above copyright
500 * notice, this list of conditions and the following disclaimer.
501 *
502 * 2. Redistributions in binary form must reproduce the above copyright
503 * notice, this list of conditions and the following disclaimer in
504 * the documentation and/or other materials provided with the
505 * distribution.
506 *
507 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
508 * and "Vovida Open Communication Application Library (VOCAL)" must
509 * not be used to endorse or promote products derived from this
510 * software without prior written permission. For written
511 * permission, please contact vocal@vovida.org.
512 *
513 * 4. Products derived from this software may not be called "VOCAL", nor
514 * may "VOCAL" appear in their name, without prior written
515 * permission of Vovida Networks, Inc.
516 *
517 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
518 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
519 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
520 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
521 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
522 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
523 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
524 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
525 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
526 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
527 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
528 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
529 * DAMAGE.
530 *
531 * ====================================================================
532 *
533 * This software consists of voluntary contributions made by Vovida
534 * Networks, Inc. and many individuals on behalf of Vovida Networks,
535 * Inc. For more information on Vovida Networks, Inc., please see
536 * <http://www.vovida.org/>.
537 *
538 */
#define max(x, y)
#define resip_assert(x)
This file needs to work for both C and C++ code.
The base class from which various templated Fifo classes are derived.
virtual void onFifoPolled()
uint64_t mLastSampleTakenMicroSec
bool getMultiple(int ms, Messages &other, unsigned int max)
bool getNext(int ms, T &toReturn)
Returns the next message available.
virtual time_t getTimeDepth() const
computes the time delta between the oldest and newest queue members
uint32_t mAverageServiceTimeMicroSec
virtual time_t expectedWaitTimeMilliSec() const
Returns the expected time it will take to service all messages currently in the queue (in milli-secon...
virtual unsigned int size() const
get the current size of the fifo.
virtual void onMessagePopped(unsigned int num=1)
Called when a message (or messages) are removed from this fifo.
Condition mCondition
condition for waiting on new queue items
T getNext()
Returns the first message available.
bool messageAvailable() const
is a message available?
std::deque< T > Messages
bool empty() const
is the queue empty?
size_t add(const T &item)
size_t addMultiple(Messages &items)
virtual void clear()
remove all elements in the queue (or not)
virtual size_t getCountDepth() const
Returns the number of elements in the FIFO.
AbstractFifo()
Constructor.
Messages mFifo
container for FIFO items
virtual time_t averageServiceTimeMicroSec() const
Returns the average time it takes for individual messages to be serviced (in micro-seconds)
void getMultiple(Messages &other, unsigned int max)
Mutex mMutex
access serialization lock
virtual void onMessagePushed(int num)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Interface for providing metrics on FIFOs, primarily used by CongestionManager.
virtual time_t averageServiceTimeMicroSec() const =0
Returns the average time it takes for individual messages to be serviced (in micro-seconds)
virtual const resip::Data & getDescription() const
Gets the description for this fifo.
void setDescription(const resip::Data &description)
Sets the description for this fifo.
virtual time_t getTimeDepth() const =0
Returns the difference in time between the youngest and oldest item in the FIFO in seconds.
virtual size_t getCountDepth() const =0
Returns the number of elements in the FIFO.
virtual time_t expectedWaitTimeMilliSec() const =0
Returns the expected time it will take to service all messages currently in the queue (in milli-secon...
void setRole(uint8_t role)
static uint64_t getTimeMicroSec()
Returns the current clock time in microseconds.
Definition Timer.hxx:66
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
std::mutex Mutex
A semaphore that can be locked by only one thread at a time.
Definition Mutex.hxx:37
const _Tp1 resipIntDiv(const _Tp1 &__a, const _Tp2 &__b)
Definition compat.hxx:206
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
Definition Lock.hxx:28
unsigned long long uint64_t
Definition Stun.hxx:39
unsigned int uint32_t
Definition Stun.hxx:34
std::condition_variable Condition
A condition variable that can be signaled or waited on, wraps POSIX/Windows implementations depending...
Definition Condition.hxx:51
unsigned char uint8_t
Definition Stun.hxx:29