diff options
author | Armin Berres <armin.berres@basyskom.de> | 2010-07-13 13:43:05 +0200 |
---|---|---|
committer | Sergiy Dubovik <sergiy.dubovik@nokia.com> | 2010-07-20 14:11:51 +0300 |
commit | 86fa0df092dd1f541f114a02586d0f6a6d3b0fe4 (patch) | |
tree | db725c00c035f14331fe4c22f86472ea45c9368d | |
parent | 68bca5c5188e721ce55f508409d276190beb910e (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.cpp | 59 | ||||
-rw-r--r-- | mthemedaemon/mthemedaemonserver.h | 16 | ||||
-rw-r--r-- | src/corelib/theme/mcommonpixmaps.cpp | 51 | ||||
-rw-r--r-- | src/corelib/theme/mcommonpixmaps.h | 5 | ||||
-rw-r--r-- | src/corelib/theme/mremotethemedaemon.cpp | 53 | ||||
-rw-r--r-- | src/corelib/theme/mremotethemedaemon.h | 1 | ||||
-rw-r--r-- | src/corelib/theme/mremotethemedaemon_p.h | 3 | ||||
-rw-r--r-- | src/corelib/theme/mthemedaemon.h | 4 |
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; |