⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gaprate.hh

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 HH
字号:
// -*- c-basic-offset: 4; related-file-name: "../../lib/gaprate.cc" -*-#ifndef CLICK_GAPRATE_HH#define CLICK_GAPRATE_HH#include <click/timestamp.hh>CLICK_DECLSclass ErrorHandler;/** @file <click/gaprate.hh> *  @brief  A Click helper class for implementing a uniform rate. *//** @class GapRate include/click/gaprate.hh <click/gaprate.hh> *  @brief  A helper class for implementing a uniform rate. * *  The GapRate class helps its user implement a process with a uniform rate: *  a process in which one user event happens every T seconds.  GapRate is *  designed to efficiently model high rates.  (Contrast this with Timer, *  which can serve a similar function at low rates.) * *  GapRate models an underlying "true" rated process with the correct rate. *  It also keeps a counter, maintained by its user via the update() method, *  that measures the progress of the user's rated process.  The *  needs_update() method compares this counter with its expected value, which *  is determined by the true rated process.  If the user's rated process is *  running behind, then needs_update() returns true; the user should trigger *  an event and call the update() method.  If the user's rated process is *  just right or is running faster than the true process, then needs_update() *  returns false; the user should <em>not</em> trigger an event. * *  Creating a non-bursty rate can be expensive and difficult.  GapRate *  attempts to create a non-bursty rate using timestamps and some interesting *  microsecond-based arithmetic.  External factors can cause scheduling *  hiccups where GapRate is not called as much as expected.  GapRate *  compensates for hiccups: the user's rated process may fall up to a full *  second behind the true rated process, then catch up in a burst.  More than *  one second's worth of lag is ignored. * *  The maximum rate GapRate can implement is MAX_RATE events per second. * *  @sa  Timer */class GapRate { public:    /** @brief  Construct a GapRate object with initial rate 0. */    inline GapRate();    /** @brief  Construct a GapRate object with initial rate @a r.     *  @param  r  initial rate (events per second) */    inline GapRate(unsigned r);    /** @brief  Return the current rate. */    inline unsigned rate() const;    /** @brief  Set the current rate to @a r.     *  @param  r  desired rate (events per second)     *     *  Rates larger than MAX_RATE are reduced to MAX_RATE.  Also performs the     *  equivalent of a reset() to flush old state. */    inline void set_rate(unsigned r);    /** @brief  Set the current rate to @a r.     *  @param  r     desired rate (events per second)     *  @param  errh  error handler     *     *  Acts like set_rate(@a r), except that an warning is reported to @a errh     *  if @a r is larger than MAX_RATE. */    void set_rate(unsigned r, ErrorHandler *errh);    /** @brief  Returns whether the user's rate is behind the true rate.     *  @param  ts  current timestamp     *     *  Returns true iff the user's rate is currently behind the true rate,     *  meaning the user should cause an event and call update(). */    inline bool need_update(const Timestamp &ts);    /** @brief  Returns a time when the user's rate will be behind the true rate.     *  @pre  need_update() has been called at least once.     *  @return If the rate is 0, or need_update() has not been called,     *  returns Timestamp().  If the user's rate is already behind the true     *  rate, returns a time no greater than the argument passed to the last     *  need_update().  Otherwise, returns a time in the future when     *  need_update() will return true.     */    inline Timestamp expiry() const;    /** @brief  Increment the user event counter.     *     *  Call this function when causing a user event. */    inline void update();    /** @brief  Increment the user event counter by @a delta.     *  @param  delta  number of user events     *     *  @note This may be faster than calling update() @a delta times.     *  Furthermore, @a delta can be negative. */    inline void update_with(int delta);    /** @brief  Resets the true rate counter.     *     *  This function flushes any old information about the true rate counter     *  and its relationship to the user's rate counter. */    inline void reset();    enum { UGAP_SHIFT = 12 };    enum { MAX_RATE = 1000000U << UGAP_SHIFT };  private:    unsigned _ugap;		// (1000000 << UGAP_SHIFT) / _rate    int _sec_count;		// number of updates this second so far    Timestamp::seconds_type _tv_sec;	// current second    unsigned _rate;		// desired rate#if DEBUG_GAPRATE    Timestamp _last;#endif};/** @brief  Reset the underlying rated process. */inline voidGapRate::reset(){    _tv_sec = -1;#if DEBUG_GAPRATE    _last.set_sec(0);#endif}inline voidGapRate::set_rate(unsigned r){    if (r > MAX_RATE)	r = MAX_RATE;    _rate = r;    _ugap = (r == 0 ? MAX_RATE + 1 : MAX_RATE / r);#if DEBUG_GAPRATE    click_chatter("ugap: %u", _ugap);#endif    reset();}inlineGapRate::GapRate(){    set_rate(0);}inlineGapRate::GapRate(unsigned r){    set_rate(r);}inline unsignedGapRate::rate() const{    return _rate;}inline boolGapRate::need_update(const Timestamp &now){    // this is an approximation of:    // unsigned need = (unsigned) ((now.usec() / 1000000.0) * _rate)    unsigned need = (now.usec() << UGAP_SHIFT) / _ugap;    if (_tv_sec < 0) {	// 27.Feb.2005: often OK to send a packet after reset unless rate is	// 0 -- requested by Bart Braem	// check include/click/gaprate.hh (1.2)	_tv_sec = now.sec();	_sec_count = need + ((now.usec() << UGAP_SHIFT) - (need * _ugap) > _ugap / 2);    } else if (now.sec() > _tv_sec) {	_tv_sec = now.sec();	if (_sec_count > 0)	    _sec_count -= _rate;    }#if DEBUG_GAPRATE    click_chatter("%{timestamp} -> %u @ %u [%d]", &now, need, _sec_count, (int)need >= _sec_count);#endif    return ((int)need >= _sec_count);}inline voidGapRate::update(){    _sec_count++;}inline voidGapRate::update_with(int delta){    _sec_count += delta;}inline TimestampGapRate::expiry() const{    if (_tv_sec < 0 || _rate == 0)        return Timestamp();    else if (_sec_count < 0)	return Timestamp(_tv_sec, 0);    else {	Timestamp::seconds_type sec = _tv_sec;	int count = _sec_count;	if ((unsigned) count >= _rate) {	    sec += count / _rate;	    count = count % _rate;	}	// uint32_t usec = (int) (count * 1000000.0 / _rate)	uint32_t usec = (count * _ugap) >> UGAP_SHIFT;	return Timestamp::make_usec(sec, usec);    }}CLICK_ENDDECLS#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -