- 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)
|
||||
{
|
||||
if (value.isNull() || !value.isValid()) {
|
||||
if (!d->data.contains(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->data.remove(key);
|
||||
} else {
|
||||
d->data[key] = value;
|
||||
}
|
||||
|
||||
d->dirty = true;
|
||||
d->updateTs = QTime::currentTime().msec();
|
||||
}
|
||||
|
||||
void DataContainer::clearData()
|
||||
@ -73,10 +70,35 @@ void DataContainer::checkForUpdate()
|
||||
{
|
||||
if (d->dirty) {
|
||||
emit updated(objectName(), d->data);
|
||||
|
||||
foreach (SignalRelay* relay, d->relays) {
|
||||
relay->checkQueueing();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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
|
||||
// and it still doesn't want to connect to a relay, so we have
|
||||
// nothing to do!
|
||||
kDebug() << " already connected, nothing to do";
|
||||
//kDebug() << " already connected, nothing to do";
|
||||
return;
|
||||
} else {
|
||||
disconnect(this, SIGNAL(updated(QString,Plasma::DataEngine::Data)),
|
||||
@ -119,7 +141,7 @@ void DataContainer::connectVisualization(QObject* visualization, uint updateInte
|
||||
|
||||
if (!connected) {
|
||||
connect(visualization, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(disconnectVisualization(QObject*)), Qt::QueuedConnection);
|
||||
this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
d->relayObjects[visualization] = 0;
|
||||
|
@ -80,6 +80,16 @@ class PLASMA_EXPORT DataContainer : public QObject
|
||||
**/
|
||||
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:
|
||||
/**
|
||||
* 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,
|
||||
* requests to be updated.
|
||||
**/
|
||||
void requestUpdate(const QString& source);
|
||||
void requestUpdate(DataContainer *source);
|
||||
|
||||
private:
|
||||
friend class SignalRelay;
|
||||
|
@ -30,7 +30,8 @@ class DataContainer::Private
|
||||
{
|
||||
public:
|
||||
Private()
|
||||
: dirty(false)
|
||||
: updateTs(0),
|
||||
dirty(false)
|
||||
{}
|
||||
|
||||
QObject* signalRelay(const DataContainer* dc, QObject *visualization,
|
||||
@ -39,6 +40,7 @@ public:
|
||||
DataEngine::Data data;
|
||||
QMap<QObject *, SignalRelay *> relayObjects;
|
||||
QMap<uint, SignalRelay *> relays;
|
||||
int updateTs;
|
||||
bool dirty : 1;
|
||||
};
|
||||
|
||||
@ -53,8 +55,10 @@ public:
|
||||
d(data),
|
||||
m_interval(ival),
|
||||
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);
|
||||
if (m_align != Plasma::NoAlignment) {
|
||||
checkAlignment();
|
||||
@ -92,12 +96,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void checkQueueing() {
|
||||
if (m_queued) {
|
||||
emit updated(dc->objectName(), d->data);
|
||||
m_queued = false;
|
||||
}
|
||||
}
|
||||
|
||||
DataContainer *dc;
|
||||
DataContainer::Private *d;
|
||||
uint m_interval;
|
||||
Plasma::IntervalAlignment m_align;
|
||||
int m_timerId;
|
||||
bool m_resetTimer;
|
||||
bool m_queued;
|
||||
|
||||
signals:
|
||||
void updated(const QString&, const Plasma::DataEngine::Data&);
|
||||
@ -115,7 +127,12 @@ protected:
|
||||
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);
|
||||
event->accept();
|
||||
}
|
||||
|
@ -70,13 +70,13 @@ class DataEngine::Private
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* kDebug() << "DataEngine " << engine->objectName()
|
||||
/*kDebug() << "DataEngine " << engine->objectName()
|
||||
<< ": could not find DataContainer " << sourceName
|
||||
<< ", creating" << endl;*/
|
||||
DataContainer* s = new DataContainer(engine);
|
||||
s->setObjectName(sourceName);
|
||||
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) {
|
||||
trimQueue();
|
||||
@ -88,6 +88,7 @@ class DataEngine::Private
|
||||
|
||||
void connectSource(DataContainer* s, QObject* visualization, uint updateInterval, Plasma::IntervalAlignment align)
|
||||
{
|
||||
//kDebug() << "connect source called with interval" << updateInterval;
|
||||
if (updateInterval > 0) {
|
||||
// never more frequently than allowed, never more than 20 times per second
|
||||
uint min = qMax(50, minUpdateFreq); // for qMin below
|
||||
@ -106,26 +107,31 @@ class DataEngine::Private
|
||||
|
||||
DataContainer* requestSource(const QString& sourceName)
|
||||
{
|
||||
//kDebug() << "requesting source " << sourceName;
|
||||
DataContainer* s = source(sourceName, false);
|
||||
|
||||
if (!s) {
|
||||
// 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)) {
|
||||
s = source(sourceName, false);
|
||||
if (s) {
|
||||
// now we have a source; since it was created on demand, assume
|
||||
// it should be removed when not used
|
||||
connect(s, SIGNAL(unused(QString)), engine, SLOT(removeSource(QString)));
|
||||
connect(s, SIGNAL(requestUpdate(QString)), engine, SLOT(internalUpdateSource(QString)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void trimQueue()
|
||||
{
|
||||
while (sourceQueue.count() >= limit) {
|
||||
uint queueCount = sourceQueue.count();
|
||||
while (queueCount >= limit) {
|
||||
DataContainer* punted = sourceQueue.dequeue();
|
||||
engine->removeSource(punted->objectName());
|
||||
}
|
||||
@ -177,13 +183,13 @@ QStringList DataEngine::sources() const
|
||||
void DataEngine::connectSource(const QString& source, QObject* visualization,
|
||||
uint updateInterval, Plasma::IntervalAlignment intervalAlignment) const
|
||||
{
|
||||
//kDebug() << "connectSource" << source;
|
||||
DataContainer* s = d->requestSource(source);
|
||||
|
||||
if (!s) {
|
||||
return;
|
||||
if (s) {
|
||||
d->connectSource(s, visualization, updateInterval, intervalAlignment);
|
||||
//kDebug() << " ==> source connected";
|
||||
}
|
||||
|
||||
d->connectSource(s, visualization, updateInterval, intervalAlignment);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!s) {
|
||||
return;
|
||||
if (s) {
|
||||
s->disconnectVisualization(visualization);
|
||||
}
|
||||
|
||||
s->disconnectVisualization(visualization);
|
||||
}
|
||||
|
||||
DataContainer* DataEngine::containerForSource(const QString &source)
|
||||
@ -228,9 +232,18 @@ void DataEngine::startInit()
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -251,7 +264,7 @@ bool DataEngine::sourceRequested(const QString &name)
|
||||
bool DataEngine::updateSource(const QString& 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?
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,7 @@ class PLASMA_EXPORT DataEngine : public QObject
|
||||
/**
|
||||
* @internal
|
||||
**/
|
||||
void internalUpdateSource(const QString& source);
|
||||
void internalUpdateSource(DataContainer* source);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
|
Loading…
Reference in New Issue
Block a user