aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Berres <armin.berres@basyskom.de>2010-07-13 13:43:05 +0200
committerSergiy Dubovik <sergiy.dubovik@nokia.com>2010-07-20 14:11:51 +0300
commit86fa0df092dd1f541f114a02586d0f6a6d3b0fe4 (patch)
treedb725c00c035f14331fe4c22f86472ea45c9368d
parent68bca5c5188e721ce55f508409d276190beb910e (diff)
Changes: themedaemon sends most used pixmap handles to the clients
RevBy: Peter Penz Details: The themedaemon keeps internally a list of most used pixmaps which are always hold in memory. When a client requests a pixmap from this list the pixmap can be returned faster. Ideally the client would not have to query the themedaemon at all but just know about the handles if the most used pixmaps. With this commit the themedaemon sends the handles of the most used pixmaps to the clients when they register and keeps them up to date if the list of most used pixmaps changes. If a client uses one of these pixmaps it notifies the themedaemon so it can keep statistics about most used pixmaps up to date.
-rw-r--r--mthemedaemon/mthemedaemonserver.cpp59
-rw-r--r--mthemedaemon/mthemedaemonserver.h16
-rw-r--r--src/corelib/theme/mcommonpixmaps.cpp51
-rw-r--r--src/corelib/theme/mcommonpixmaps.h5
-rw-r--r--src/corelib/theme/mremotethemedaemon.cpp53
-rw-r--r--src/corelib/theme/mremotethemedaemon.h1
-rw-r--r--src/corelib/theme/mremotethemedaemon_p.h3
-rw-r--r--src/corelib/theme/mthemedaemon.h4
8 files changed, 179 insertions, 13 deletions
diff --git a/mthemedaemon/mthemedaemonserver.cpp b/mthemedaemon/mthemedaemonserver.cpp
index a17323f1..849dec4c 100644
--- a/mthemedaemon/mthemedaemonserver.cpp
+++ b/mthemedaemon/mthemedaemonserver.cpp
@@ -35,7 +35,8 @@ MThemeDaemonServer::MThemeDaemonServer() :
currentTheme("/meegotouch/theme/name"),
currentLocale("/meegotouch/i18n/language"),
defaultTheme(M_THEME_DEFAULT),
- delayedThemeChange(false)
+ delayedThemeChange(false),
+ sequenceCounter(0)
{
// 1) make sure that gconf has some value for the current theme
if (currentTheme.value().isNull() || currentTheme.value().toString().isEmpty() )
@@ -85,6 +86,7 @@ MThemeDaemonServer::MThemeDaemonServer() :
processQueueTimer.setInterval(0);
processQueueTimer.setSingleShot(false);
connect(&processQueueTimer, SIGNAL(timeout()), SLOT(processOneQueueItem()));
+ connect(&daemon.mostUsedPixmaps, SIGNAL(mostUsedPixmapsChanged(M::MThemeDaemonProtocol::MostUsedPixmaps)), this, SLOT(handleUpdatedMostUsedPixmaps(M::MThemeDaemonProtocol::MostUsedPixmaps)));
}
MThemeDaemonServer::~MThemeDaemonServer()
@@ -189,6 +191,8 @@ void MThemeDaemonServer::clientDataAvailable()
daemon.addClient(client);
client->stream() << Packet(Packet::ThemeChangedPacket, packet.sequenceNumber(),
new ThemeChangeInfo(daemon.themeInheritanceChain(), daemon.themeLibraryNames()));
+ client->stream() << Packet(Packet::MostUsedPixmapsPacket, ++sequenceCounter,
+ new MostUsedPixmaps(daemon.mostUsedPixmaps.mostUsedPixmapHandles(), QList<PixmapIdentifier>()));
break;
}
}
@@ -211,6 +215,12 @@ void MThemeDaemonServer::clientDataAvailable()
new ThemeChangeInfo(daemon.themeInheritanceChain(), daemon.themeLibraryNames()));
} break;
+ case Packet::PixmapUsedPacket: {
+ // client wants to use a pixmap
+ const PixmapIdentifier *id = static_cast<const PixmapIdentifier *>(packet.data());
+ pixmapUsed(client, *id, packet.sequenceNumber());
+ } break;
+
case Packet::RequestPixmapPacket: {
// client requested a pixmap
const PixmapIdentifier *id = static_cast<const PixmapIdentifier *>(packet.data());
@@ -236,6 +246,10 @@ void MThemeDaemonServer::clientDataAvailable()
themeChangeApplied(client, packet.sequenceNumber());
} break;
+ case Packet::AckMostUsedPixmapsPacket: {
+ ackMostUsedPixmaps(client, packet.sequenceNumber());
+ } break;
+
case Packet::QueryThemeDaemonStatusPacket: {
themeDaemonStatus(client, packet.sequenceNumber());
} break;
@@ -398,6 +412,34 @@ void MThemeDaemonServer::processOneQueueItem()
}
}
+void MThemeDaemonServer::handleUpdatedMostUsedPixmaps(const M::MThemeDaemonProtocol::MostUsedPixmaps& mostUsed)
+{
+ quint64 sequenceNumber = ++sequenceCounter;
+
+ foreach(MThemeDaemonClient * c, registeredClients) {
+ c->stream() << Packet(Packet::MostUsedPixmapsPacket, sequenceNumber, new MostUsedPixmaps(mostUsed));
+ if (!mostUsed.removedIdentifiers.empty()) {
+ clientsThatHaveNotYetUpdatedMostUsed[sequenceNumber].append(c);
+ }
+ }
+ if (!mostUsed.removedIdentifiers.empty()) {
+ pixmapsToDeleteWhenUpdatedMostUsed[sequenceNumber] = mostUsed.removedIdentifiers;
+ }
+}
+
+void MThemeDaemonServer::pixmapUsed(MThemeDaemonClient *client,
+ const PixmapIdentifier &id, quint64 sequenceNumber)
+{
+ Q_UNUSED(sequenceNumber)
+ // if the client has requested a release for this pixmap, we'll remove the
+ // release request, otherwise we increase the reference count
+ const QueueItem item (client, id, sequenceNumber);
+ if (!releasePixmapsQueue.removeOne(item)) {
+ Qt::HANDLE handle;
+ daemon.pixmap(item.client, item.pixmapId, handle);
+ }
+}
+
void MThemeDaemonServer::pixmapRequested(MThemeDaemonClient *client,
const PixmapIdentifier &id, quint64 sequenceNumber)
{
@@ -471,6 +513,21 @@ void MThemeDaemonServer::themeChangeApplied(MThemeDaemonClient *client,
}
}
+void MThemeDaemonServer::ackMostUsedPixmaps(MThemeDaemonClient *client,
+ quint64 sequenceNumber)
+{
+ if(!clientsThatHaveNotYetUpdatedMostUsed[sequenceNumber].removeOne(client)) {
+ mWarning("MThemeDaemonServer") << "Client" << client->name() << "has already acked most used pixmaps packet!";
+ return;
+ }
+
+ if (clientsThatHaveNotYetUpdatedMostUsed.empty()) {
+ foreach(const PixmapIdentifier& id, pixmapsToDeleteWhenUpdatedMostUsed[sequenceNumber]) {
+ pixmapReleaseRequested(client, id, sequenceNumber);
+ }
+ }
+}
+
void MThemeDaemonServer::themeDaemonStatus(MThemeDaemonClient *client,
quint64 sequenceNumber) const
{
diff --git a/mthemedaemon/mthemedaemonserver.h b/mthemedaemon/mthemedaemonserver.h
index 346e504c..8114c1b8 100644
--- a/mthemedaemon/mthemedaemonserver.h
+++ b/mthemedaemon/mthemedaemonserver.h
@@ -52,16 +52,23 @@ private slots:
void processOneQueueItem();
+ void handleUpdatedMostUsedPixmaps(const M::MThemeDaemonProtocol::MostUsedPixmaps& mostUsed);
+
private:
+ void pixmapUsed(MThemeDaemonClient *client,
+ const M::MThemeDaemonProtocol::PixmapIdentifier &id,
+ quint64 sequenceNumber);
void pixmapRequested(MThemeDaemonClient *client,
- const M::MThemeDaemonProtocol::PixmapIdentifier &id,
- quint64 sequenceNumber);
+ const M::MThemeDaemonProtocol::PixmapIdentifier &id,
+ quint64 sequenceNumber);
void pixmapReleaseRequested(MThemeDaemonClient *client,
const M::MThemeDaemonProtocol::PixmapIdentifier &id,
quint64 sequenceNumber);
void themeChangeApplied(MThemeDaemonClient *client, quint64 sequenceNumber);
+ void ackMostUsedPixmaps(MThemeDaemonClient *client, quint64 sequenceNumber);
+
void themeDaemonStatus(MThemeDaemonClient *client, quint64 sequenceNumber) const;
private:
@@ -97,6 +104,11 @@ private:
QList<MThemeDaemonClient*> clientsThatHaveNotYetAppliedThemeChange;
QList<QPixmap*> pixmapsToDeleteWhenThemeChangeHasCompleted;
+
+ QHash<quint64, QList<MThemeDaemonClient*> > clientsThatHaveNotYetUpdatedMostUsed;
+ QHash<quint64, QList<M::MThemeDaemonProtocol::PixmapIdentifier> > pixmapsToDeleteWhenUpdatedMostUsed;
+
+ quint64 sequenceCounter;
};
//! \internal_end
#endif
diff --git a/src/corelib/theme/mcommonpixmaps.cpp b/src/corelib/theme/mcommonpixmaps.cpp
index 55e0c931..6b9c359c 100644
--- a/src/corelib/theme/mcommonpixmaps.cpp
+++ b/src/corelib/theme/mcommonpixmaps.cpp
@@ -148,10 +148,7 @@ void MCommonPixmaps::loadOne()
if (!toLoadList.isEmpty()) {
PixmapIdentifier id = *toLoadList.begin();
toLoadList.erase(toLoadList.begin());
- if (!toLoadList.isEmpty()) {
- // there's still items in the list, so start the timer with small delay
- cpuMonitor.start(250);
- }
+
ImageResource *resource = daemon->findImageResource(id.imageId);
if (resource) {
bool resourceLoaded = false;
@@ -171,6 +168,16 @@ void MCommonPixmaps::loadOne()
requestCounts.remove(id);
mostUsedPixmaps.remove(id);
}
+
+ if (!toLoadList.isEmpty()) {
+ // there's still items in the list, so start the timer with small delay
+ cpuMonitor.start(250);
+ } else {
+ // all common pixmaps loaded - notify clients
+ MostUsedPixmaps mostUsed;
+ mostUsed.addedHandles = mostUsedPixmapHandles();
+ emit mostUsedPixmapsChanged(mostUsed);
+ }
}
} else {
// the cpu usage was too high, so start start the timer with longer delay
@@ -194,8 +201,14 @@ void MCommonPixmaps::increaseRequestCount(const M::MThemeDaemonProtocol::PixmapI
// check if there's still room for this pixmap
if (mostUsedPixmaps.count() < MCommonPixmaps::CacheSize) {
// yep, just add this pixmap and return
- resource->fetchPixmap(id.size);
+ Qt::HANDLE handle = resource->fetchPixmap(id.size);
mostUsedPixmaps.insert(id);
+
+ MostUsedPixmaps packet;
+ packet.addedHandles.append(PixmapHandle(id, handle));
+ if (toLoadList.isEmpty()) {
+ emit mostUsedPixmapsChanged(packet);
+ }
return;
}
@@ -229,13 +242,16 @@ void MCommonPixmaps::increaseRequestCount(const M::MThemeDaemonProtocol::PixmapI
minRequestsForCache = (secondlyLeastUsedRequests > requestCount.value()) ? requestCount.value() : secondlyLeastUsedRequests;
// allocate one pixmap for the list
- resource->fetchPixmap(id.size);
+ Qt::HANDLE handle = resource->fetchPixmap(id.size);
+ MostUsedPixmaps packet;
+ packet.addedHandles.append(PixmapHandle(id, handle));
// release the old one from the list
if (!toLoadList.remove(*leastUsed)) {
- // resource was loaded
- resource = daemon->findImageResource(leastUsed->imageId);
- resource->releasePixmap(leastUsed->size);
+ packet.removedIdentifiers.append(id);
+ }
+ if (toLoadList.isEmpty()) {
+ emit mostUsedPixmapsChanged(packet);
}
remove(*leastUsed);
@@ -254,6 +270,23 @@ void MCommonPixmaps::reload(const PixmapIdentifier &id, ImageResource *oldResour
toLoadList.insert(id);
}
+QList<M::MThemeDaemonProtocol::PixmapHandle> MCommonPixmaps::mostUsedPixmapHandles()
+{
+ if (!toLoadList.isEmpty()) {
+ // not all pixmaps loaded/valid - return empty list
+ return QList<M::MThemeDaemonProtocol::PixmapHandle>();
+ }
+
+ // we could also save the handles earlier but it is cheap to do the query
+ QList<PixmapHandle> pixmapHandles;
+ foreach(const M::MThemeDaemonProtocol::PixmapIdentifier& id, mostUsedPixmaps) {
+ Qt::HANDLE handle = daemon->findImageResource(id.imageId)->pixmapHandle(id.size);
+ pixmapHandles.append(M::MThemeDaemonProtocol::PixmapHandle(id, handle));
+ }
+
+ return pixmapHandles;
+}
+
void MCommonPixmaps::remove(const M::MThemeDaemonProtocol::PixmapIdentifier &id)
{
// path to theme-specific cache
diff --git a/src/corelib/theme/mcommonpixmaps.h b/src/corelib/theme/mcommonpixmaps.h
index 2b53b25e..f3fcea9c 100644
--- a/src/corelib/theme/mcommonpixmaps.h
+++ b/src/corelib/theme/mcommonpixmaps.h
@@ -43,6 +43,11 @@ public:
void reload(const M::MThemeDaemonProtocol::PixmapIdentifier &id, ImageResource *oldResource);
+ QList<M::MThemeDaemonProtocol::PixmapHandle> mostUsedPixmapHandles();
+
+Q_SIGNALS:
+ void mostUsedPixmapsChanged(const M::MThemeDaemonProtocol::MostUsedPixmaps& mostUsed);
+
private slots:
void loadOne();
private:
diff --git a/src/corelib/theme/mremotethemedaemon.cpp b/src/corelib/theme/mremotethemedaemon.cpp
index db44b56b..82e63c34 100644
--- a/src/corelib/theme/mremotethemedaemon.cpp
+++ b/src/corelib/theme/mremotethemedaemon.cpp
@@ -177,6 +177,26 @@ quint64 MRemoteThemeDaemonPrivate::requestPixmap(const QString &imageId, const Q
return sequenceNumber;
}
+void MRemoteThemeDaemonPrivate::addMostUsedPixmaps(const QList<PixmapHandle>& handles)
+{
+ QList<PixmapHandle>::const_iterator it = handles.begin();
+ while (it != handles.end()) {
+ if (!mostUsedPixmaps.contains(it->identifier)) {
+ mostUsedPixmaps[it->identifier] = it->pixmapHandle;
+ }
+ ++it;
+ }
+}
+
+void MRemoteThemeDaemonPrivate::removeMostUsedPixmaps(const QList<PixmapIdentifier>& identifiers)
+{
+ QList<PixmapIdentifier>::const_iterator it2 = identifiers.begin();
+ while (it2 != identifiers.end()) {
+ mostUsedPixmaps.remove(*it2);
+ ++it2;
+ }
+}
+
void MRemoteThemeDaemon::pixmapHandleSync(const QString &imageId, const QSize &size)
{
Q_D(MRemoteThemeDaemon);
@@ -191,9 +211,32 @@ void MRemoteThemeDaemon::pixmapHandle(const QString &imageId, const QSize &size)
{
Q_D(MRemoteThemeDaemon);
+ Qt::HANDLE handle = pixmapHandleFromMostUsed(imageId, size);
+ if (handle) {
+ emit pixmapCreated(imageId, size, handle);
+ return;
+ }
+
d->requestPixmap(imageId, size);
}
+Qt::HANDLE MRemoteThemeDaemon::pixmapHandleFromMostUsed(const QString &imageId, const QSize &size)
+{
+ Q_D(MRemoteThemeDaemon);
+
+ PixmapIdentifier identifier(imageId, size);
+ QHash<PixmapIdentifier, Qt::HANDLE>::iterator it = d->mostUsedPixmaps.find(identifier);
+ if (it != d->mostUsedPixmaps.end())
+ {
+ int sequenceNumber = ++d->sequenceCounter;
+ d->stream << Packet(Packet::PixmapUsedPacket, sequenceNumber, new PixmapIdentifier(imageId, size));
+
+ return it.value();
+ }
+
+ return 0;
+}
+
void MRemoteThemeDaemon::releasePixmap(const QString &imageId, const QSize &size)
{
Q_D(MRemoteThemeDaemon);
@@ -260,6 +303,15 @@ void MRemoteThemeDaemonPrivate::processOnePacket(const Packet &packet)
emit q->themeChangeCompleted();
} break;
+ case Packet::MostUsedPixmapsPacket: {
+ const MostUsedPixmaps *mostUsedPacket = static_cast<const MostUsedPixmaps*>(packet.data());
+ addMostUsedPixmaps(mostUsedPacket->addedHandles);
+ if (!mostUsedPacket->removedIdentifiers.empty()) {
+ removeMostUsedPixmaps(mostUsedPacket->removedIdentifiers);
+ stream << Packet(Packet::AckMostUsedPixmapsPacket, packet.sequenceNumber());
+ }
+ } break;
+
default:
mDebug("MRemoteThemeDaemon") << "Couldn't process packet of type" << packet.type();
break;
@@ -293,6 +345,7 @@ void MRemoteThemeDaemonPrivate::pixmapUpdated(const PixmapHandle &handle)
void MRemoteThemeDaemonPrivate::themeChanged(const QStringList &themeInheritanceChain, const QStringList &themeLibraryNames)
{
Q_Q(MRemoteThemeDaemon);
+ mostUsedPixmaps.clear();
this->themeInheritanceChain = themeInheritanceChain;
this->themeLibraryNames = themeLibraryNames;
emit q->themeChanged(themeInheritanceChain, themeLibraryNames);
diff --git a/src/corelib/theme/mremotethemedaemon.h b/src/corelib/theme/mremotethemedaemon.h
index 9c6451be..a125859d 100644
--- a/src/corelib/theme/mremotethemedaemon.h
+++ b/src/corelib/theme/mremotethemedaemon.h
@@ -41,6 +41,7 @@ public:
virtual void pixmapHandleSync(const QString &imageId, const QSize &size);
virtual void pixmapHandle(const QString &imageId, const QSize &size);
+ Qt::HANDLE pixmapHandleFromMostUsed(const QString &imageId, const QSize &size);
virtual void releasePixmap(const QString &imageId, const QSize &size);
virtual QString currentTheme();
diff --git a/src/corelib/theme/mremotethemedaemon_p.h b/src/corelib/theme/mremotethemedaemon_p.h
index 4ccf916e..b5cc8c02 100644
--- a/src/corelib/theme/mremotethemedaemon_p.h
+++ b/src/corelib/theme/mremotethemedaemon_p.h
@@ -31,6 +31,7 @@ class MRemoteThemeDaemonPrivate
{
public:
QHash<M::MThemeDaemonProtocol::PixmapIdentifier, quint64> pixmapRequests;
+ QHash<M::MThemeDaemonProtocol::PixmapIdentifier, Qt::HANDLE> mostUsedPixmaps;
M::MThemeDaemonProtocol::Packet readOnePacket();
void processOnePacket(const M::MThemeDaemonProtocol::Packet &packet);
@@ -40,6 +41,8 @@ public:
void themeChanged(const QStringList &themeInheritanceChain, const QStringList &themeLibraryNames);
bool waitForServer(const QString &serverAddress, int timeout);
M::MThemeDaemonProtocol::Packet waitForPacket(quint64 sequenceNumber);
+ void addMostUsedPixmaps(const QList<M::MThemeDaemonProtocol::PixmapHandle>& handles);
+ void removeMostUsedPixmaps(const QList<M::MThemeDaemonProtocol::PixmapIdentifier>& identifiers);
Q_DECLARE_PUBLIC(MRemoteThemeDaemon)
MRemoteThemeDaemon *q_ptr;
diff --git a/src/corelib/theme/mthemedaemon.h b/src/corelib/theme/mthemedaemon.h
index 1272f2ea..c261d638 100644
--- a/src/corelib/theme/mthemedaemon.h
+++ b/src/corelib/theme/mthemedaemon.h
@@ -54,11 +54,13 @@ public:
QString currentTheme() const;
ImageResource *findImageResource(const QString &imageId);
+
+ MCommonPixmaps mostUsedPixmaps;
+
private:
void reloadImagePaths(const QString &locale);
private:
- MCommonPixmaps mostUsedPixmaps;
QString currentThemeName;
QStringList themeInheritance;
QStringList themeLibraries;