- when an intervalled visualization triggers an update, but the update is async, we queue up to trigger updated when the data _actually_ arrives.
- timestamp sources on update so we don't over update them due to multiple visualizations hammering on it. improves our tick situation even more. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=712188
This commit is contained in:
parent
0fc83b6e76
commit
6ffbc459ad
@ -46,16 +46,13 @@ const DataEngine::Data DataContainer::data() const
|
|||||||
void DataContainer::setData(const QString& key, const QVariant& value)
|
void DataContainer::setData(const QString& key, const QVariant& value)
|
||||||
{
|
{
|
||||||
if (value.isNull() || !value.isValid()) {
|
if (value.isNull() || !value.isValid()) {
|
||||||
if (!d->data.contains(key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->data.remove(key);
|
d->data.remove(key);
|
||||||
} else {
|
} else {
|
||||||
d->data[key] = value;
|
d->data[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->dirty = true;
|
d->dirty = true;
|
||||||
|
d->updateTs = QTime::currentTime().msec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataContainer::clearData()
|
void DataContainer::clearData()
|
||||||
@ -73,10 +70,35 @@ void DataContainer::checkForUpdate()
|
|||||||
{
|
{
|
||||||
if (d->dirty) {
|
if (d->dirty) {
|
||||||
emit updated(objectName(), d->data);
|
emit updated(objectName(), d->data);
|
||||||
|
|
||||||
|
foreach (SignalRelay* relay, d->relays) {
|
||||||
|
relay->checkQueueing();
|
||||||
|
}
|
||||||
|
|
||||||
d->dirty = false;
|
d->dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint DataContainer::timeSinceLastUpdate() const
|
||||||
|
{
|
||||||
|
int msec = QTime::currentTime().msec();
|
||||||
|
if (msec < d->updateTs) {
|
||||||
|
// we wrapped over midnight here, so return the current
|
||||||
|
// msec's plus the number of msec left in the previous day.
|
||||||
|
// 86400000 is the # of msec in a day
|
||||||
|
//
|
||||||
|
// yes, we assume we don't wrap more than one day here.
|
||||||
|
return msec + (86400000 - d->updateTs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msec - d->updateTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataContainer::hasUpdates() const
|
||||||
|
{
|
||||||
|
return d->dirty;
|
||||||
|
}
|
||||||
|
|
||||||
void DataContainer::checkUsage()
|
void DataContainer::checkUsage()
|
||||||
{
|
{
|
||||||
if (d->relays.count() < 1 &&
|
if (d->relays.count() < 1 &&
|
||||||
@ -109,7 +131,7 @@ void DataContainer::connectVisualization(QObject* visualization, uint updateInte
|
|||||||
// the visualization was connected already, but not to a relay
|
// the visualization was connected already, but not to a relay
|
||||||
// and it still doesn't want to connect to a relay, so we have
|
// and it still doesn't want to connect to a relay, so we have
|
||||||
// nothing to do!
|
// nothing to do!
|
||||||
kDebug() << " already connected, nothing to do";
|
//kDebug() << " already connected, nothing to do";
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
disconnect(this, SIGNAL(updated(QString,Plasma::DataEngine::Data)),
|
disconnect(this, SIGNAL(updated(QString,Plasma::DataEngine::Data)),
|
||||||
@ -119,7 +141,7 @@ void DataContainer::connectVisualization(QObject* visualization, uint updateInte
|
|||||||
|
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
connect(visualization, SIGNAL(destroyed(QObject*)),
|
connect(visualization, SIGNAL(destroyed(QObject*)),
|
||||||
this, SLOT(disconnectVisualization(QObject*)), Qt::QueuedConnection);
|
this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->relayObjects[visualization] = 0;
|
d->relayObjects[visualization] = 0;
|
||||||
|
@ -80,6 +80,16 @@ class PLASMA_EXPORT DataContainer : public QObject
|
|||||||
**/
|
**/
|
||||||
void checkForUpdate();
|
void checkForUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how long ago, in msecs, that the data in this container was last updated
|
||||||
|
**/
|
||||||
|
uint timeSinceLastUpdate() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
**/
|
||||||
|
bool hasUpdates() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/**
|
/**
|
||||||
* Check if the DataContainer is still in use.
|
* Check if the DataContainer is still in use.
|
||||||
@ -118,7 +128,7 @@ class PLASMA_EXPORT DataContainer : public QObject
|
|||||||
* Emitted when the source, usually due to an internal timer firing,
|
* Emitted when the source, usually due to an internal timer firing,
|
||||||
* requests to be updated.
|
* requests to be updated.
|
||||||
**/
|
**/
|
||||||
void requestUpdate(const QString& source);
|
void requestUpdate(DataContainer *source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SignalRelay;
|
friend class SignalRelay;
|
||||||
|
@ -30,7 +30,8 @@ class DataContainer::Private
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Private()
|
Private()
|
||||||
: dirty(false)
|
: updateTs(0),
|
||||||
|
dirty(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
QObject* signalRelay(const DataContainer* dc, QObject *visualization,
|
QObject* signalRelay(const DataContainer* dc, QObject *visualization,
|
||||||
@ -39,6 +40,7 @@ public:
|
|||||||
DataEngine::Data data;
|
DataEngine::Data data;
|
||||||
QMap<QObject *, SignalRelay *> relayObjects;
|
QMap<QObject *, SignalRelay *> relayObjects;
|
||||||
QMap<uint, SignalRelay *> relays;
|
QMap<uint, SignalRelay *> relays;
|
||||||
|
int updateTs;
|
||||||
bool dirty : 1;
|
bool dirty : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,8 +55,10 @@ public:
|
|||||||
d(data),
|
d(data),
|
||||||
m_interval(ival),
|
m_interval(ival),
|
||||||
m_align(align),
|
m_align(align),
|
||||||
m_resetTimer(false)
|
m_resetTimer(false),
|
||||||
|
m_queued(false)
|
||||||
{
|
{
|
||||||
|
//kDebug() << "signal relay with time of" << m_timerId << "being set up";
|
||||||
m_timerId = startTimer(m_interval);
|
m_timerId = startTimer(m_interval);
|
||||||
if (m_align != Plasma::NoAlignment) {
|
if (m_align != Plasma::NoAlignment) {
|
||||||
checkAlignment();
|
checkAlignment();
|
||||||
@ -92,12 +96,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkQueueing() {
|
||||||
|
if (m_queued) {
|
||||||
|
emit updated(dc->objectName(), d->data);
|
||||||
|
m_queued = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataContainer *dc;
|
DataContainer *dc;
|
||||||
DataContainer::Private *d;
|
DataContainer::Private *d;
|
||||||
uint m_interval;
|
uint m_interval;
|
||||||
Plasma::IntervalAlignment m_align;
|
Plasma::IntervalAlignment m_align;
|
||||||
int m_timerId;
|
int m_timerId;
|
||||||
bool m_resetTimer;
|
bool m_resetTimer;
|
||||||
|
bool m_queued;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updated(const QString&, const Plasma::DataEngine::Data&);
|
void updated(const QString&, const Plasma::DataEngine::Data&);
|
||||||
@ -115,7 +127,12 @@ protected:
|
|||||||
checkAlignment();
|
checkAlignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dc->requestUpdate(dc->objectName());
|
emit dc->requestUpdate(dc);
|
||||||
|
if (!dc->hasUpdates()) {
|
||||||
|
// the source wasn't actually updated; so let's put ourselves in the queue
|
||||||
|
// so we get an updated() when the data does arrive
|
||||||
|
m_queued = true;
|
||||||
|
}
|
||||||
emit updated(dc->objectName(), d->data);
|
emit updated(dc->objectName(), d->data);
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
@ -70,13 +70,13 @@ class DataEngine::Private
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* kDebug() << "DataEngine " << engine->objectName()
|
/*kDebug() << "DataEngine " << engine->objectName()
|
||||||
<< ": could not find DataContainer " << sourceName
|
<< ": could not find DataContainer " << sourceName
|
||||||
<< ", creating" << endl;*/
|
<< ", creating" << endl;*/
|
||||||
DataContainer* s = new DataContainer(engine);
|
DataContainer* s = new DataContainer(engine);
|
||||||
s->setObjectName(sourceName);
|
s->setObjectName(sourceName);
|
||||||
sources.insert(sourceName, s);
|
sources.insert(sourceName, s);
|
||||||
connect(s, SIGNAL(requestUpdate(QString)), engine, SLOT(internalUpdateSource(QString)));
|
connect(s, SIGNAL(requestUpdate(DataContainer*)), engine, SLOT(internalUpdateSource(DataContainer*)));
|
||||||
|
|
||||||
if (limit > 0) {
|
if (limit > 0) {
|
||||||
trimQueue();
|
trimQueue();
|
||||||
@ -88,6 +88,7 @@ class DataEngine::Private
|
|||||||
|
|
||||||
void connectSource(DataContainer* s, QObject* visualization, uint updateInterval, Plasma::IntervalAlignment align)
|
void connectSource(DataContainer* s, QObject* visualization, uint updateInterval, Plasma::IntervalAlignment align)
|
||||||
{
|
{
|
||||||
|
//kDebug() << "connect source called with interval" << updateInterval;
|
||||||
if (updateInterval > 0) {
|
if (updateInterval > 0) {
|
||||||
// never more frequently than allowed, never more than 20 times per second
|
// never more frequently than allowed, never more than 20 times per second
|
||||||
uint min = qMax(50, minUpdateFreq); // for qMin below
|
uint min = qMax(50, minUpdateFreq); // for qMin below
|
||||||
@ -106,26 +107,31 @@ class DataEngine::Private
|
|||||||
|
|
||||||
DataContainer* requestSource(const QString& sourceName)
|
DataContainer* requestSource(const QString& sourceName)
|
||||||
{
|
{
|
||||||
|
//kDebug() << "requesting source " << sourceName;
|
||||||
DataContainer* s = source(sourceName, false);
|
DataContainer* s = source(sourceName, false);
|
||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
// we didn't find a data source, so give the engine an opportunity to make one
|
// we didn't find a data source, so give the engine an opportunity to make one
|
||||||
|
/*kDebug() << "DataEngine " << engine->objectName()
|
||||||
|
<< ": could not find DataContainer " << sourceName
|
||||||
|
<< " will create on request" << endl;*/
|
||||||
if (engine->sourceRequested(sourceName)) {
|
if (engine->sourceRequested(sourceName)) {
|
||||||
s = source(sourceName, false);
|
s = source(sourceName, false);
|
||||||
if (s) {
|
if (s) {
|
||||||
// now we have a source; since it was created on demand, assume
|
// now we have a source; since it was created on demand, assume
|
||||||
// it should be removed when not used
|
// it should be removed when not used
|
||||||
connect(s, SIGNAL(unused(QString)), engine, SLOT(removeSource(QString)));
|
connect(s, SIGNAL(unused(QString)), engine, SLOT(removeSource(QString)));
|
||||||
connect(s, SIGNAL(requestUpdate(QString)), engine, SLOT(internalUpdateSource(QString)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trimQueue()
|
void trimQueue()
|
||||||
{
|
{
|
||||||
while (sourceQueue.count() >= limit) {
|
uint queueCount = sourceQueue.count();
|
||||||
|
while (queueCount >= limit) {
|
||||||
DataContainer* punted = sourceQueue.dequeue();
|
DataContainer* punted = sourceQueue.dequeue();
|
||||||
engine->removeSource(punted->objectName());
|
engine->removeSource(punted->objectName());
|
||||||
}
|
}
|
||||||
@ -177,13 +183,13 @@ QStringList DataEngine::sources() const
|
|||||||
void DataEngine::connectSource(const QString& source, QObject* visualization,
|
void DataEngine::connectSource(const QString& source, QObject* visualization,
|
||||||
uint updateInterval, Plasma::IntervalAlignment intervalAlignment) const
|
uint updateInterval, Plasma::IntervalAlignment intervalAlignment) const
|
||||||
{
|
{
|
||||||
|
//kDebug() << "connectSource" << source;
|
||||||
DataContainer* s = d->requestSource(source);
|
DataContainer* s = d->requestSource(source);
|
||||||
|
|
||||||
if (!s) {
|
if (s) {
|
||||||
return;
|
d->connectSource(s, visualization, updateInterval, intervalAlignment);
|
||||||
|
//kDebug() << " ==> source connected";
|
||||||
}
|
}
|
||||||
|
|
||||||
d->connectSource(s, visualization, updateInterval, intervalAlignment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataEngine::connectAllSources(QObject* visualization, uint updateInterval,
|
void DataEngine::connectAllSources(QObject* visualization, uint updateInterval,
|
||||||
@ -198,11 +204,9 @@ void DataEngine::disconnectSource(const QString& source, QObject* visualization)
|
|||||||
{
|
{
|
||||||
DataContainer* s = d->source(source, false);
|
DataContainer* s = d->source(source, false);
|
||||||
|
|
||||||
if (!s) {
|
if (s) {
|
||||||
return;
|
s->disconnectVisualization(visualization);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->disconnectVisualization(visualization);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataContainer* DataEngine::containerForSource(const QString &source)
|
DataContainer* DataEngine::containerForSource(const QString &source)
|
||||||
@ -228,9 +232,18 @@ void DataEngine::startInit()
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataEngine::internalUpdateSource(const QString& source)
|
void DataEngine::internalUpdateSource(DataContainer* source)
|
||||||
{
|
{
|
||||||
if (updateSource(source)) {
|
if (d->minUpdateFreq > 0 &&
|
||||||
|
source->timeSinceLastUpdate() < d->minUpdateFreq) {
|
||||||
|
// skip updating this source; it's been too soon
|
||||||
|
//TODO: should we queue an update in this case? return to this
|
||||||
|
// once we see the results in real world usage
|
||||||
|
//kDebug() << "internal update source is delaying" << source->timeSinceLastUpdate() << d->minUpdateFreq;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateSource(source->objectName())) {
|
||||||
d->queueUpdate();
|
d->queueUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +264,7 @@ bool DataEngine::sourceRequested(const QString &name)
|
|||||||
bool DataEngine::updateSource(const QString& source)
|
bool DataEngine::updateSource(const QString& source)
|
||||||
{
|
{
|
||||||
Q_UNUSED(source);
|
Q_UNUSED(source);
|
||||||
kDebug() << "updateSource source" << endl;
|
//kDebug() << "updateSource source" << endl;
|
||||||
return false; //TODO: should this be true to trigger, even needless, updates on every tick?
|
return false; //TODO: should this be true to trigger, even needless, updates on every tick?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ class PLASMA_EXPORT DataEngine : public QObject
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
**/
|
**/
|
||||||
void internalUpdateSource(const QString& source);
|
void internalUpdateSource(DataContainer* source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Private;
|
class Private;
|
||||||
|
Loading…
Reference in New Issue
Block a user