Move Average into average.hh
Moved the class to a more appropriate place.
This commit is contained in:
@ -13,6 +13,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <maxbase/ccdefs.hh>
|
||||
#include <maxbase/atomic.hh>
|
||||
#include <maxbase/assert.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -152,4 +154,241 @@ private:
|
||||
int m_num_samples = 0;
|
||||
double m_ave = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Average is a base class for classes intended to be used for calculating
|
||||
* averages. An Average may have a dependant Average whose value depends
|
||||
* upon the value of the first. At certain moments, an Average may trigger
|
||||
* its dependant Average to update itself.
|
||||
*/
|
||||
class Average
|
||||
{
|
||||
Average(const Average&) = delete;
|
||||
Average& operator=(const Average&) = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pDependant An optional dependant average.
|
||||
*/
|
||||
Average(Average* pDependant = NULL)
|
||||
: m_pDependant(pDependant)
|
||||
, m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to the Average. The exact meaning depends upon the
|
||||
* concrete Average class.
|
||||
*
|
||||
* If the addition of the value in some sense represents a full cycle
|
||||
* in the average calculation, then the instance will call add_value()
|
||||
* on its dependant, otherwise it will call update_value(). In both cases
|
||||
* with its own value as argument.
|
||||
*
|
||||
* @param value The value to be added.
|
||||
*
|
||||
* @return True if the addition of the value caused a full cycle
|
||||
* in the average calculation, false otherwise.
|
||||
*/
|
||||
virtual bool add_value(uint8_t value) = 0;
|
||||
|
||||
/**
|
||||
* Update the value of the Average. The exact meaning depends upon the
|
||||
* concrete Average class. Will also call update_value() of its dependant
|
||||
* with its own value as argument.
|
||||
*
|
||||
* @param value The value to be updated.
|
||||
*/
|
||||
virtual void update_value(uint8_t value) = 0;
|
||||
|
||||
/**
|
||||
* Return the average value.
|
||||
*
|
||||
* @return The value represented by the Average.
|
||||
*/
|
||||
uint8_t value() const
|
||||
{
|
||||
return mxb::atomic::load(&m_value);
|
||||
}
|
||||
|
||||
protected:
|
||||
Average* m_pDependant; /*< The optional dependant Average. */
|
||||
uint32_t m_value; /*< The current average value. */
|
||||
|
||||
protected:
|
||||
void set_value(uint32_t value)
|
||||
{
|
||||
mxb::atomic::store(&m_value, value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An Average consisting of a single value.
|
||||
*/
|
||||
class Average1 : public Average
|
||||
{
|
||||
public:
|
||||
Average1(Average* pDependant = NULL)
|
||||
: Average(pDependant)
|
||||
{
|
||||
}
|
||||
|
||||
bool add_value(uint8_t value)
|
||||
{
|
||||
set_value(value);
|
||||
|
||||
// Every addition of a value represents a full cycle.
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->add_value(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_value(uint8_t value)
|
||||
{
|
||||
set_value(value);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->update_value(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An Average calculated from N values.
|
||||
*/
|
||||
template<size_t N>
|
||||
class AverageN : public Average
|
||||
{
|
||||
public:
|
||||
AverageN(Average* pDependant = NULL)
|
||||
: Average(pDependant)
|
||||
, m_end(m_begin + N)
|
||||
, m_i(m_begin)
|
||||
, m_sum(0)
|
||||
, m_nValues(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool add_value(uint8_t value)
|
||||
{
|
||||
if (m_nValues == N)
|
||||
{
|
||||
// If as many values that fit has been added, then remove the
|
||||
// least recent value from the sum.
|
||||
m_sum -= *m_i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise make a note that a new value is added.
|
||||
++m_nValues;
|
||||
}
|
||||
|
||||
*m_i = value;
|
||||
m_sum += *m_i; // Update the sum of all values.
|
||||
|
||||
m_i = next(m_i);
|
||||
|
||||
uint32_t average = m_sum / m_nValues;
|
||||
|
||||
set_value(average);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
if (m_i == m_begin)
|
||||
{
|
||||
// If we have looped around we have performed a full cycle and will
|
||||
// add a new value to the dependant average.
|
||||
m_pDependant->add_value(average);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we just update the most recent value.
|
||||
m_pDependant->update_value(average);
|
||||
}
|
||||
}
|
||||
|
||||
return m_i == m_begin;
|
||||
}
|
||||
|
||||
void update_value(uint8_t value)
|
||||
{
|
||||
if (m_nValues == 0)
|
||||
{
|
||||
// If no values have been added yet, there's nothing to update but we
|
||||
// need to add the value.
|
||||
add_value(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we update the most recent value.
|
||||
uint8_t* p = prev(m_i);
|
||||
|
||||
m_sum -= *p;
|
||||
*p = value;
|
||||
m_sum += *p;
|
||||
|
||||
uint32_t average = m_sum / m_nValues;
|
||||
|
||||
set_value(average);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->update_value(average);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* prev(uint8_t* p)
|
||||
{
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
if (p > m_begin)
|
||||
{
|
||||
--p;
|
||||
}
|
||||
else
|
||||
{
|
||||
mxb_assert(p == m_begin);
|
||||
p = m_end - 1;
|
||||
}
|
||||
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
uint8_t* next(uint8_t* p)
|
||||
{
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
++p;
|
||||
|
||||
if (p == m_end)
|
||||
{
|
||||
p = m_begin;
|
||||
}
|
||||
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_begin[N]; /*< Buffer containing values from which the average is calculated. */
|
||||
uint8_t* m_end; /*< Points to one past the end of the buffer. */
|
||||
uint8_t* m_i; /*< Current position in the buffer. */
|
||||
uint32_t m_sum; /*< Sum of all values in the buffer. */
|
||||
uint32_t m_nValues; /*< How many values the buffer contains. */
|
||||
};
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <maxbase/assert.h>
|
||||
#include <maxbase/atomic.h>
|
||||
#include <maxbase/average.hh>
|
||||
#include <maxbase/messagequeue.hh>
|
||||
#include <maxbase/semaphore.hh>
|
||||
#include <maxbase/worker.h>
|
||||
@ -175,244 +176,6 @@ public:
|
||||
static uint64_t get_time();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Average is a base class for classes intended to be used for calculating
|
||||
* averages. An Average may have a dependant Average whose value depends
|
||||
* upon the value of the first. At certain moments, an Average may trigger
|
||||
* its dependant Average to update itself.
|
||||
*/
|
||||
class Average
|
||||
{
|
||||
Average(const Average&) = delete;
|
||||
Average& operator=(const Average&) = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pDependant An optional dependant average.
|
||||
*/
|
||||
Average(Average* pDependant = NULL)
|
||||
: m_pDependant(pDependant)
|
||||
, m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Average();
|
||||
|
||||
/**
|
||||
* Add a value to the Average. The exact meaning depends upon the
|
||||
* concrete Average class.
|
||||
*
|
||||
* If the addition of the value in some sense represents a full cycle
|
||||
* in the average calculation, then the instance will call add_value()
|
||||
* on its dependant, otherwise it will call update_value(). In both cases
|
||||
* with its own value as argument.
|
||||
*
|
||||
* @param value The value to be added.
|
||||
*
|
||||
* @return True if the addition of the value caused a full cycle
|
||||
* in the average calculation, false otherwise.
|
||||
*/
|
||||
virtual bool add_value(uint8_t value) = 0;
|
||||
|
||||
/**
|
||||
* Update the value of the Average. The exact meaning depends upon the
|
||||
* concrete Average class. Will also call update_value() of its dependant
|
||||
* with its own value as argument.
|
||||
*
|
||||
* @param value The value to be updated.
|
||||
*/
|
||||
virtual void update_value(uint8_t value) = 0;
|
||||
|
||||
/**
|
||||
* Return the average value.
|
||||
*
|
||||
* @return The value represented by the Average.
|
||||
*/
|
||||
uint8_t value() const
|
||||
{
|
||||
return atomic_load_uint32(&m_value);
|
||||
}
|
||||
|
||||
protected:
|
||||
Average* m_pDependant; /*< The optional dependant Average. */
|
||||
uint32_t m_value; /*< The current average value. */
|
||||
|
||||
protected:
|
||||
void set_value(uint32_t value)
|
||||
{
|
||||
atomic_store_uint32(&m_value, value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An Average consisting of a single value.
|
||||
*/
|
||||
class Average1 : public Average
|
||||
{
|
||||
public:
|
||||
Average1(Average* pDependant = NULL)
|
||||
: Average(pDependant)
|
||||
{
|
||||
}
|
||||
|
||||
bool add_value(uint8_t value)
|
||||
{
|
||||
set_value(value);
|
||||
|
||||
// Every addition of a value represents a full cycle.
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->add_value(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_value(uint8_t value)
|
||||
{
|
||||
set_value(value);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->update_value(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An Average calculated from N values.
|
||||
*/
|
||||
template<size_t N>
|
||||
class AverageN : public Average
|
||||
{
|
||||
public:
|
||||
AverageN(Average* pDependant = NULL)
|
||||
: Average(pDependant)
|
||||
, m_end(m_begin + N)
|
||||
, m_i(m_begin)
|
||||
, m_sum(0)
|
||||
, m_nValues(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool add_value(uint8_t value)
|
||||
{
|
||||
if (m_nValues == N)
|
||||
{
|
||||
// If as many values that fit has been added, then remove the
|
||||
// least recent value from the sum.
|
||||
m_sum -= *m_i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise make a note that a new value is added.
|
||||
++m_nValues;
|
||||
}
|
||||
|
||||
*m_i = value;
|
||||
m_sum += *m_i; // Update the sum of all values.
|
||||
|
||||
m_i = next(m_i);
|
||||
|
||||
uint32_t average = m_sum / m_nValues;
|
||||
|
||||
set_value(average);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
if (m_i == m_begin)
|
||||
{
|
||||
// If we have looped around we have performed a full cycle and will
|
||||
// add a new value to the dependant average.
|
||||
m_pDependant->add_value(average);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we just update the most recent value.
|
||||
m_pDependant->update_value(average);
|
||||
}
|
||||
}
|
||||
|
||||
return m_i == m_begin;
|
||||
}
|
||||
|
||||
void update_value(uint8_t value)
|
||||
{
|
||||
if (m_nValues == 0)
|
||||
{
|
||||
// If no values have been added yet, there's nothing to update but we
|
||||
// need to add the value.
|
||||
add_value(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we update the most recent value.
|
||||
uint8_t* p = prev(m_i);
|
||||
|
||||
m_sum -= *p;
|
||||
*p = value;
|
||||
m_sum += *p;
|
||||
|
||||
uint32_t average = m_sum / m_nValues;
|
||||
|
||||
set_value(average);
|
||||
|
||||
if (m_pDependant)
|
||||
{
|
||||
m_pDependant->update_value(average);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* prev(uint8_t* p)
|
||||
{
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
if (p > m_begin)
|
||||
{
|
||||
--p;
|
||||
}
|
||||
else
|
||||
{
|
||||
mxb_assert(p == m_begin);
|
||||
p = m_end - 1;
|
||||
}
|
||||
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
uint8_t* next(uint8_t* p)
|
||||
{
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
++p;
|
||||
|
||||
if (p == m_end)
|
||||
{
|
||||
p = m_begin;
|
||||
}
|
||||
|
||||
mxb_assert(p >= m_begin);
|
||||
mxb_assert(p < m_end);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_begin[N]; /*< Buffer containing values from which the average is calculated. */
|
||||
uint8_t* m_end; /*< Points to one past the end of the buffer. */
|
||||
uint8_t* m_i; /*< Current position in the buffer. */
|
||||
uint32_t m_sum; /*< Sum of all values in the buffer. */
|
||||
uint32_t m_nValues; /*< How many values the buffer contains. */
|
||||
};
|
||||
|
||||
uint64_t m_start_time; /*< When was the current 1-second period started. */
|
||||
uint64_t m_wait_start; /*< The time when the worker entered epoll_wait(). */
|
||||
|
@ -103,10 +103,6 @@ void WorkerLoad::about_to_work(uint64_t now)
|
||||
}
|
||||
}
|
||||
|
||||
WorkerLoad::Average::~Average()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
uint64_t WorkerLoad::get_time()
|
||||
{
|
||||
|
Reference in New Issue
Block a user