Commit abe00120 authored by Alessio Bonfiglio's avatar Alessio Bonfiglio Committed by Arjen Hiemstra
Browse files

Add support for an iterator based aggregate function in AggregateSensor

While working on this [mr](ksystemstats!21) I ended up needing a way to compute the average of the sensor values inside AggregateSensor.
The solution I ended up with (hoping I haven't over-engineered it) is to add support to a new kind of aggregate function that gives the user an iterator (technically two, begin and end) over the sensor values that gives him more flexibility respect the old method. Note that this solution is a superset of the previous one, that, in fact, can still be used if needed (this mr simply add a wrapper around the old kind of aggregate functions in order to make them compatible with the new ones).
A good portion of code in this merge request is due to need of separating the implementation of the iterator (PrivateIterator) from the interface given to the user (SensorIterator) in the same way that AggregateSensor is different from Private.

NOTE: this mr technically breaks the compatibility with the codes that uses aggregateFunction() (the getter) because now this function return the new kind of aggregate function (and the signature). Not knowing if this function was used actually anywhere and disliking the idea of keeping the old behavior (because now that old aggregate function can be null if the new one is used) I changed the code this way, but I can easily revert it by also keeping track of the old type of aggregate function if this is needed.
parent 821864f6
Pipeline #204921 passed with stage
in 1 minute and 35 seconds
......@@ -66,14 +66,37 @@ class Q_DECL_HIDDEN AggregateSensor::Private
public:
QRegularExpression matchObjects;
QString matchProperty;
QHash<QString, QPointer<SensorProperty>> sensors;
SensorHash sensors;
bool dataChangeQueued = false;
int dataCompressionDuration = 100;
SensorContainer *subsystem = nullptr;
std::function<QVariant(QVariant, QVariant)> aggregateFunction;
std::function<QVariant(AggregateSensor::SensorIterator, const AggregateSensor::SensorIterator)> aggregateFunction;
};
QVariant AggregateSensor::SensorIterator::operator*() const
{
return m_it.value()->value();
}
AggregateSensor::SensorIterator &AggregateSensor::SensorIterator::operator++()
{
do {
++m_it;
} while (!(m_it == m_end || m_it.value()));
return *this;
}
bool AggregateSensor::SensorIterator::operator==(const SensorIterator &other) const
{
return m_it == other.m_it;
}
bool AggregateSensor::SensorIterator::operator!=(const SensorIterator &other) const
{
return m_it != other.m_it;
}
AggregateSensor::AggregateSensor(SensorObject *provider, const QString &id, const QString &name)
: AggregateSensor(provider, id, name, QVariant{})
{
......@@ -84,7 +107,7 @@ AggregateSensor::AggregateSensor(SensorObject *provider, const QString &id, cons
, d(std::make_unique<Private>())
{
d->subsystem = qobject_cast<SensorContainer *>(provider->parent());
d->aggregateFunction = addVariants;
setAggregateFunction(addVariants);
connect(d->subsystem, &SensorContainer::objectAdded, this, &AggregateSensor::updateSensors);
connect(d->subsystem, &SensorContainer::objectRemoved, this, &AggregateSensor::updateSensors);
}
......@@ -111,13 +134,10 @@ QVariant AggregateSensor::value() const
return QVariant{};
}
QVariant result = it.value()->value();
it++;
for (; it != d->sensors.constEnd(); it++) {
if (it.value()) {
result = d->aggregateFunction(result, it.value()->value());
}
}
auto begin = SensorIterator(it, d->sensors.constEnd());
const auto end = SensorIterator(d->sensors.constEnd(), d->sensors.constEnd());
auto result = d->aggregateFunction(begin, end);
return result;
}
......@@ -158,12 +178,27 @@ void AggregateSensor::setMatchSensors(const QRegularExpression &objectIds, const
updateSensors();
}
std::function<QVariant(QVariant, QVariant)> AggregateSensor::aggregateFunction() const
std::function<QVariant(AggregateSensor::SensorIterator, AggregateSensor::SensorIterator)> AggregateSensor::aggregateFunction() const
{
return d->aggregateFunction;
}
void AggregateSensor::setAggregateFunction(const std::function<QVariant(QVariant, QVariant)> &newAggregateFunction)
{
auto aggregateFunction = [newAggregateFunction](AggregateSensor::SensorIterator begin, const AggregateSensor::SensorIterator end) -> QVariant {
auto &it = begin;
QVariant result = *begin;
++it;
for (; it != end; ++it) {
result = newAggregateFunction(result, *it);
}
return result;
};
d->aggregateFunction = aggregateFunction;
}
void AggregateSensor::setAggregateFunction(const std::function<QVariant(SensorIterator, const SensorIterator)> &newAggregateFunction)
{
d->aggregateFunction = newAggregateFunction;
}
......
......@@ -22,6 +22,9 @@
namespace KSysGuard
{
using SensorHash = QHash<QString, QPointer<SensorProperty>>;
/**
* @todo write docs
*/
......@@ -38,10 +41,28 @@ public:
void subscribe() override;
void unsubscribe() override;
class SensorIterator
{
public:
SensorIterator(SensorHash::const_iterator begin, const SensorHash::const_iterator end)
: m_it(begin)
, m_end(end){};
QVariant operator*() const;
SensorIterator &operator++();
bool operator==(const SensorIterator &other) const;
bool operator!=(const SensorIterator &other) const;
private:
SensorHash::const_iterator m_it;
const SensorHash::const_iterator m_end;
};
QRegularExpression matchSensors() const;
void setMatchSensors(const QRegularExpression &objectMatch, const QString &propertyId);
std::function<QVariant(QVariant, QVariant)> aggregateFunction() const;
std::function<QVariant(SensorIterator, const SensorIterator)> aggregateFunction() const;
void setAggregateFunction(const std::function<QVariant(QVariant, QVariant)> &function);
void setAggregateFunction(const std::function<QVariant(SensorIterator, const SensorIterator)> &function);
void addSensor(SensorProperty *sensor);
void removeSensor(const QString &sensorPath);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment