diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-06-25 08:07:37 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-06-25 13:50:45 +0200 |
commit | b1f238568214e6587b829d6695677e55a99b1d40 (patch) | |
tree | 0e7b0c4f99dd8ad0be16db6a81cf8e2c2c64282f /examples/quick/imageresponseprovider | |
parent | 4d9ffeff745a4a8bd31df7af85058d38383c5286 (diff) |
Discourage having AsyncImageResponse inherit from QRunnable
As the AsyncImageResponse is owned by the qml engine, it should ideally
live in the same thread. Else, when we call destroyLater() on it in the
qml engine, we can run into various race coditions.
see also commit c8827b444c23656f67feee2e3ebd4f2868ab3db7
Change-Id: I6e21ca4527281445e5f6df082f60b60838bb2eac
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'examples/quick/imageresponseprovider')
-rw-r--r-- | examples/quick/imageresponseprovider/imageresponseprovider.cpp | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.cpp b/examples/quick/imageresponseprovider/imageresponseprovider.cpp index 4f7c12b1d8..32510dbec8 100644 --- a/examples/quick/imageresponseprovider/imageresponseprovider.cpp +++ b/examples/quick/imageresponseprovider/imageresponseprovider.cpp @@ -57,40 +57,60 @@ #include <QImage> #include <QThreadPool> -class AsyncImageResponse : public QQuickImageResponse, public QRunnable +class AsyncImageResponseRunnable : public QObject, public QRunnable +{ + Q_OBJECT + +signals: + void done(QImage image); + +public: + AsyncImageResponseRunnable(const QString &id, const QSize &requestedSize) + : m_id(id), m_requestedSize(requestedSize) {} + + void run() override + { + auto image = QImage(50, 50, QImage::Format_RGB32); + if (m_id == QLatin1String("slow")) { + qDebug() << "Slow, red, sleeping for 5 seconds"; + QThread::sleep(5); + image.fill(Qt::red); + } else { + qDebug() << "Fast, blue, sleeping for 1 second"; + QThread::sleep(1); + image.fill(Qt::blue); + } + if (m_requestedSize.isValid()) + image = image.scaled(m_requestedSize); + + emit done(image); + } + +private: + QString m_id; + QSize m_requestedSize; +}; + +class AsyncImageResponse : public QQuickImageResponse { public: - AsyncImageResponse(const QString &id, const QSize &requestedSize) - : m_id(id), m_requestedSize(requestedSize) + AsyncImageResponse(const QString &id, const QSize &requestedSize, QThreadPool *pool) { - setAutoDelete(false); + auto runnable = new AsyncImageResponseRunnable(id, requestedSize); + connect(runnable, &AsyncImageResponseRunnable::done, this, &AsyncImageResponse::handleDone); + pool->start(runnable); } - QQuickTextureFactory *textureFactory() const override - { - return QQuickTextureFactory::textureFactoryForImage(m_image); + void handleDone(QImage image) { + m_image = image; + emit finished(); } - void run() override + QQuickTextureFactory *textureFactory() const override { - m_image = QImage(50, 50, QImage::Format_RGB32); - if (m_id == "slow") { - qDebug() << "Slow, red, sleeping for 5 seconds"; - QThread::sleep(5); - m_image.fill(Qt::red); - } else { - qDebug() << "Fast, blue, sleeping for 1 second"; - QThread::sleep(1); - m_image.fill(Qt::blue); - } - if (m_requestedSize.isValid()) - m_image = m_image.scaled(m_requestedSize); - - emit finished(); + return QQuickTextureFactory::textureFactoryForImage(m_image); } - QString m_id; - QSize m_requestedSize; QImage m_image; }; @@ -99,8 +119,7 @@ class AsyncImageProvider : public QQuickAsyncImageProvider public: QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override { - AsyncImageResponse *response = new AsyncImageResponse(id, requestedSize); - pool.start(response); + AsyncImageResponse *response = new AsyncImageResponse(id, requestedSize, &pool); return response; } |