summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2010-02-03 08:43:00 (GMT)
committerMartin Jones <martin.jones@nokia.com>2010-02-03 08:43:00 (GMT)
commit348675876dfacb6cdd2373a1a4ae9d814e057df2 (patch)
tree192487075e60933b1db8a6dfc19ab155361f3deb /src
parent0d037da6f4a7a7da7ad319265d7abbf41295e082 (diff)
downloadQt-348675876dfacb6cdd2373a1a4ae9d814e057df2.zip
Qt-348675876dfacb6cdd2373a1a4ae9d814e057df2.tar.gz
Qt-348675876dfacb6cdd2373a1a4ae9d814e057df2.tar.bz2
Really run image reader in its own thread.
Diffstat (limited to 'src')
-rw-r--r--src/declarative/qml/qmlengine.cpp15
-rw-r--r--src/declarative/qml/qmlengine.h3
-rw-r--r--src/declarative/qml/qmlengine_p.h1
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp14
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.h6
-rw-r--r--src/declarative/util/qmlpixmapcache.cpp257
-rw-r--r--src/declarative/util/qmlpixmapcache_p.h1
7 files changed, 138 insertions, 159 deletions
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index a33aea7..8b52684 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -122,7 +122,7 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0),
globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0),
scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false),
- networkAccessManager(0), networkAccessManagerFactory(0), accessManagerValid(false),
+ networkAccessManager(0), networkAccessManagerFactory(0),
typeManager(e), uniqueId(1)
{
globalClass = new QmlGlobalScriptClass(&scriptEngine);
@@ -412,12 +412,6 @@ QmlNetworkAccessManagerFactory *QmlEngine::networkAccessManagerFactory() const
return d->networkAccessManagerFactory;
}
-void QmlEngine::namInvalidated()
-{
- Q_D(QmlEngine);
- d->accessManagerValid = false;
-}
-
/*!
Returns a common QNetworkAccessManager which can be used by any QML element
instantiated by this engine.
@@ -432,19 +426,12 @@ void QmlEngine::namInvalidated()
QNetworkAccessManager *QmlEngine::networkAccessManager() const
{
Q_D(const QmlEngine);
- if (!d->accessManagerValid) {
- delete d->networkAccessManagerFactory;
- d->networkAccessManagerFactory = 0;
- }
if (!d->networkAccessManager) {
if (d->networkAccessManagerFactory) {
- connect(d->networkAccessManagerFactory, SIGNAL(invalidated())
- , this, SLOT(namInvalidated()), Qt::UniqueConnection);
d->networkAccessManager = d->networkAccessManagerFactory->create(const_cast<QmlEngine*>(this));
} else {
d->networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(this));
}
- d->accessManagerValid = true;
}
return d->networkAccessManager;
}
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
index b9ec277..7ee014a 100644
--- a/src/declarative/qml/qmlengine.h
+++ b/src/declarative/qml/qmlengine.h
@@ -95,9 +95,6 @@ public:
Q_SIGNALS:
void quit ();
-private Q_SLOTS:
- void namInvalidated();
-
private:
Q_DECLARE_PRIVATE(QmlEngine)
};
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 6f62b40..ddb25a0 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -211,7 +211,6 @@ public:
bool inBeginCreate;
mutable QNetworkAccessManager *networkAccessManager;
mutable QmlNetworkAccessManagerFactory *networkAccessManagerFactory;
- mutable bool accessManagerValid;
QmlCompositeTypeManager typeManager;
QStringList fileImportPath;
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
index 6ae20de..76f20d8 100644
--- a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
@@ -76,18 +76,4 @@ QmlNetworkAccessManagerFactory::~QmlNetworkAccessManagerFactory()
implementation of this method is reentrant.
*/
-/*!
- Invalidates all currently created QNetworkAccessManager(s) which
- will cause create() to be called for subsequent network access.
-*/
-void QmlNetworkAccessManagerFactory::invalidate()
-{
- emit invalidated();
-}
-
-/*!
- \internal
- \fn QmlNetworkAccessManagerFactory::invalidated()
-*/
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
index f64918b..ce9860f 100644
--- a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
@@ -51,16 +51,12 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QNetworkAccessManager;
-class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory : public QObject
+class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory
{
- Q_OBJECT
public:
virtual ~QmlNetworkAccessManagerFactory();
- void invalidate();
virtual QNetworkAccessManager *create(QObject *parent) = 0;
-Q_SIGNALS:
- void invalidated();
};
QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp
index bfe99ac..755863a 100644
--- a/src/declarative/util/qmlpixmapcache.cpp
+++ b/src/declarative/util/qmlpixmapcache.cpp
@@ -75,6 +75,20 @@ inline uint qHash(const QUrl &uri)
return qHash(uri.toEncoded(QUrl::FormattingOption(0x100)));
}
+
+class QmlImageReaderEvent : public QEvent
+{
+public:
+ enum ReadError { NoError, Loading, Decoding };
+
+ QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, QImage &img)
+ : QEvent(QEvent::User), error(err), image(img) {}
+
+ ReadError error;
+ QImage image;
+};
+
+class QmlImageRequestHandler;
class QmlImageReader : public QThread
{
Q_OBJECT
@@ -89,130 +103,61 @@ public:
protected:
void run();
- bool event(QEvent *event);
-
-private slots:
- void networkRequestDone();
- void namInvalidated() {
- accessManagerValid = false;
- }
private:
- QNetworkAccessManager *networkAccessManager() {
- if (!accessManagerValid) {
- delete accessManager;
- accessManager = 0;
- }
- if (!accessManager) {
- if (engine && engine->networkAccessManagerFactory()) {
- connect(engine->networkAccessManagerFactory(), SIGNAL(invalidated())
- , this, SLOT(namInvalidated()), Qt::UniqueConnection);
- accessManager = engine->networkAccessManagerFactory()->create(this);
- } else {
- accessManager = new QNetworkAccessManager(this);
- }
- accessManagerValid = true;
- }
- return accessManager;
- }
-
QList<QmlPixmapReply*> jobs;
QList<QmlPixmapReply*> cancelled;
- QHash<QNetworkReply*,QmlPixmapReply*> replies;
- QNetworkAccessManager *accessManager;
- bool accessManagerValid;
QmlEngine *engine;
+ QmlImageRequestHandler *handler;
QMutex mutex;
+
static QHash<QmlEngine *,QmlImageReader*> readers;
+ friend class QmlImageRequestHandler;
};
QHash<QmlEngine *,QmlImageReader*> QmlImageReader::readers;
-class QmlImageReaderEvent : public QEvent
-{
-public:
- enum ReadError { NoError, Loading, Decoding };
-
- QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, QImage &img)
- : QEvent(QEvent::User), error(err), image(img) {}
-
- ReadError error;
- QImage image;
-};
-
-QmlImageReader::QmlImageReader(QmlEngine *eng)
- : QThread(eng), accessManager(0), accessManagerValid(false), engine(eng)
+class QmlImageRequestHandler : public QObject
{
- start(QThread::LowPriority);
-}
-
-QmlImageReader::~QmlImageReader()
-{
-}
-
-QmlImageReader *QmlImageReader::instance(QmlEngine *engine)
-{
- QmlImageReader *reader = readers.value(engine);
- if (!reader) {
- static QMutex rmutex;
- rmutex.lock();
- reader = new QmlImageReader(engine);
- readers.insert(engine, reader);
- rmutex.unlock();
+ Q_OBJECT
+public:
+ QmlImageRequestHandler(QmlImageReader *read, QmlEngine *eng)
+ : QObject(), accessManager(0), engine(eng), reader(read)
+ {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
- return reader;
-}
+ QmlPixmapReply *getImage(const QUrl &url);
+ void cancel(QmlPixmapReply *reply);
-QmlPixmapReply *QmlImageReader::getImage(const QUrl &url)
-{
- mutex.lock();
- QmlPixmapReply *reply = new QmlPixmapReply(engine, url);
- jobs.append(reply);
- if (jobs.count() == 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- mutex.unlock();
- return reply;
-}
+protected:
+ bool event(QEvent *event);
-void QmlImageReader::cancel(QmlPixmapReply *reply)
-{
- mutex.lock();
- if (reply->isLoading()) {
- // Already requested. Add to cancel list to be cancelled in reader thread.
- cancelled.append(reply);
- if (cancelled.count() == 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- } else {
- // Not yet processed - just remove from waiting list
- QList<QmlPixmapReply*>::iterator it = jobs.begin();
- while (it != jobs.end()) {
- QmlPixmapReply *job = *it;
- if (job == reply) {
- jobs.erase(it);
- break;
+private slots:
+ void networkRequestDone();
+
+private:
+ QNetworkAccessManager *networkAccessManager() {
+ if (!accessManager) {
+ if (engine && engine->networkAccessManagerFactory()) {
+ accessManager = engine->networkAccessManagerFactory()->create(this);
+ } else {
+ accessManager = new QNetworkAccessManager(this);
}
- ++it;
}
+ return accessManager;
}
- mutex.unlock();
-}
-void QmlImageReader::run()
-{
-#if defined(Q_OS_LINUX) && defined(SCHED_IDLE)
- struct sched_param param;
- int policy;
-
- pthread_getschedparam(pthread_self(), &policy, &param);
- pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
-#endif
+ QHash<QNetworkReply*,QmlPixmapReply*> replies;
+ QNetworkAccessManager *accessManager;
+ QmlEngine *engine;
+ QmlImageReader *reader;
+};
- exec();
-}
+//===========================================================================
-bool QmlImageReader::event(QEvent *event)
+bool QmlImageRequestHandler::event(QEvent *event)
{
if (event->type() == QEvent::User) {
static int replyDownloadProgress = -1;
@@ -224,15 +169,15 @@ bool QmlImageReader::event(QEvent *event)
replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()");
downloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- thisNetworkRequestDone = QmlImageReader::staticMetaObject.indexOfSlot("networkRequestDone()");
+ thisNetworkRequestDone = QmlImageRequestHandler::staticMetaObject.indexOfSlot("networkRequestDone()");
}
while (1) {
- mutex.lock();
+ reader->mutex.lock();
- if (cancelled.count()) {
- for (int i = 0; i < cancelled.count(); ++i) {
- QmlPixmapReply *job = cancelled.at(i);
+ if (reader->cancelled.count()) {
+ for (int i = 0; i < reader->cancelled.count(); ++i) {
+ QmlPixmapReply *job = reader->cancelled.at(i);
QNetworkReply *reply = replies.key(job, 0);
if (reply && reply->isRunning()) {
replies.remove(reply);
@@ -240,29 +185,19 @@ bool QmlImageReader::event(QEvent *event)
job->release(true);
}
}
- cancelled.clear();
+ reader->cancelled.clear();
}
- if (!accessManagerValid) {
- // throw away existing requests and reschedule.
- QHash<QNetworkReply*,QmlPixmapReply*>::iterator it = replies.begin();
- for (; it != replies.end(); ++it) {
- delete it.key();
- jobs.prepend(*it);
- }
- replies.clear();
- }
-
- if (!jobs.count() || replies.count() > maxImageRequestCount) {
- mutex.unlock();
+ if (!reader->jobs.count() || replies.count() > maxImageRequestCount) {
+ reader->mutex.unlock();
break;
}
- QmlPixmapReply *runningJob = jobs.takeFirst();
+ QmlPixmapReply *runningJob = reader->jobs.takeFirst();
runningJob->addRef();
runningJob->setLoading();
QUrl url = runningJob->url();
- mutex.unlock();
+ reader->mutex.unlock();
// fetch
QNetworkRequest req(url);
@@ -280,7 +215,7 @@ bool QmlImageReader::event(QEvent *event)
return QObject::event(event);
}
-void QmlImageReader::networkRequestDone()
+void QmlImageRequestHandler::networkRequestDone()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
QmlPixmapReply *job = replies.take(reply);
@@ -306,6 +241,84 @@ void QmlImageReader::networkRequestDone()
reply->deleteLater();
}
+//===========================================================================
+
+QmlImageReader::QmlImageReader(QmlEngine *eng)
+ : QThread(eng), engine(eng), handler(0)
+{
+ start(QThread::LowPriority);
+}
+
+QmlImageReader::~QmlImageReader()
+{
+ delete handler;
+}
+
+QmlImageReader *QmlImageReader::instance(QmlEngine *engine)
+{
+ QmlImageReader *reader = readers.value(engine);
+ if (!reader) {
+ static QMutex rmutex;
+ rmutex.lock();
+ reader = new QmlImageReader(engine);
+ readers.insert(engine, reader);
+ rmutex.unlock();
+ }
+
+ return reader;
+}
+
+QmlPixmapReply *QmlImageReader::getImage(const QUrl &url)
+{
+ mutex.lock();
+ QmlPixmapReply *reply = new QmlPixmapReply(engine, url);
+ jobs.append(reply);
+ if (jobs.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ mutex.unlock();
+ return reply;
+}
+
+void QmlImageReader::cancel(QmlPixmapReply *reply)
+{
+ mutex.lock();
+ if (reply->isLoading()) {
+ // Already requested. Add to cancel list to be cancelled in reader thread.
+ cancelled.append(reply);
+ if (cancelled.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ } else {
+ // Not yet processed - just remove from waiting list
+ QList<QmlPixmapReply*>::iterator it = jobs.begin();
+ while (it != jobs.end()) {
+ QmlPixmapReply *job = *it;
+ if (job == reply) {
+ jobs.erase(it);
+ break;
+ }
+ ++it;
+ }
+ }
+ mutex.unlock();
+}
+
+void QmlImageReader::run()
+{
+#if defined(Q_OS_LINUX) && defined(SCHED_IDLE)
+ struct sched_param param;
+ int policy;
+
+ pthread_getschedparam(pthread_self(), &policy, &param);
+ pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
+#endif
+
+ handler = new QmlImageRequestHandler(this, engine);
+
+ exec();
+}
+
+//===========================================================================
+
static bool readImage(QIODevice *dev, QPixmap *pixmap)
{
QImageReader imgio(dev);
diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h
index 0140352..c202ea8 100644
--- a/src/declarative/util/qmlpixmapcache_p.h
+++ b/src/declarative/util/qmlpixmapcache_p.h
@@ -83,6 +83,7 @@ private:
private:
Q_DISABLE_COPY(QmlPixmapReply)
Q_DECLARE_PRIVATE(QmlPixmapReply)
+ friend class QmlImageRequestHandler;
friend class QmlImageReader;
friend class QmlPixmapCache;
};