From c3aad50184be2a24659edfa6b647bb6eca25c92f Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 4 Nov 2020 13:00:17 +0100 Subject: [PATCH] QmlDesigner: Add waitForFinished to ImageCache Task-number: QDS-2998 Change-Id: I5ffb63b7345a17ccb499db876bb4dbb0a946ed85 Reviewed-by: Thomas Hartmann --- .../designercore/imagecache/imagecache.cpp | 22 ++++++++++++++---- .../imagecache/imagecachegenerator.cpp | 19 +++++++++------ .../imagecache/imagecachegenerator.h | 2 ++ .../imagecache/imagecachegeneratorinterface.h | 1 + .../designercore/include/imagecache.h | 4 ++++ tests/unit/unittest/imagecache-test.cpp | 23 +++++++++++++++++++ .../unittest/imagecachegenerator-test.cpp | 19 +++++++++++++++ tests/unit/unittest/mockimagecachegenerator.h | 1 + 8 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp index 20409eb7fa2..f64899e2a2a 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp @@ -60,10 +60,7 @@ ImageCache::ImageCache(ImageCacheStorageInterface &storage, ImageCache::~ImageCache() { clean(); - stopThread(); - m_condition.notify_all(); - if (m_backgroundThread.joinable()) - m_backgroundThread.join(); + wait(); } void ImageCache::request(Utils::SmallStringView name, @@ -88,6 +85,14 @@ void ImageCache::request(Utils::SmallStringView name, } } +void ImageCache::wait() +{ + stopThread(); + m_condition.notify_all(); + if (m_backgroundThread.joinable()) + m_backgroundThread.join(); +} + void ImageCache::requestImage(Utils::PathString name, ImageCache::CaptureCallback captureCallback, AbortCallback abortCallback) @@ -110,6 +115,13 @@ void ImageCache::clean() m_generator.clean(); } +void ImageCache::waitForFinished() +{ + wait(); + + m_generator.waitForFinished(); +} + std::tuple ImageCache::getEntry() { std::unique_lock lock{m_mutex}; @@ -160,7 +172,7 @@ void ImageCache::stopThread() bool ImageCache::isRunning() { std::unique_lock lock{m_mutex}; - return !m_finishing; + return !m_finishing || m_entries.size(); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp index 5b8f737515a..a90218fbd36 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.cpp @@ -44,11 +44,7 @@ ImageCacheGenerator::ImageCacheGenerator(ImageCacheCollectorInterface &collector ImageCacheGenerator::~ImageCacheGenerator() { clean(); - stopThread(); - m_condition.notify_all(); - - if (m_backgroundThread) - m_backgroundThread->wait(); + waitForFinished(); } void ImageCacheGenerator::generateImage(Utils::SmallStringView name, @@ -72,6 +68,15 @@ void ImageCacheGenerator::clean() m_tasks.clear(); } +void ImageCacheGenerator::waitForFinished() +{ + stopThread(); + m_condition.notify_all(); + + if (m_backgroundThread) + m_backgroundThread->wait(); +} + void ImageCacheGenerator::startGeneration() { while (isRunning()) { @@ -82,7 +87,7 @@ void ImageCacheGenerator::startGeneration() { std::lock_guard lock{m_mutex}; - if (m_finishing) { + if (m_finishing && m_tasks.empty()) { m_storage.walCheckpointFull(); return; } @@ -129,7 +134,7 @@ void ImageCacheGenerator::stopThread() bool ImageCacheGenerator::isRunning() { std::unique_lock lock{m_mutex}; - return !m_finishing; + return !m_finishing || m_tasks.size(); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h index 945d53eabe5..ae427c7b39b 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h @@ -56,6 +56,8 @@ public: AbortCallback &&abortCallback) override; void clean() override; + void waitForFinished() override; + private: struct Task { diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h index 26b96219951..a7ddc42d476 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegeneratorinterface.h @@ -45,6 +45,7 @@ public: = 0; virtual void clean() = 0; + virtual void waitForFinished() = 0; protected: ~ImageCacheGeneratorInterface() = default; diff --git a/src/plugins/qmldesigner/designercore/include/imagecache.h b/src/plugins/qmldesigner/designercore/include/imagecache.h index 4ac360c2a50..0bfcf89c2e4 100644 --- a/src/plugins/qmldesigner/designercore/include/imagecache.h +++ b/src/plugins/qmldesigner/designercore/include/imagecache.h @@ -60,6 +60,7 @@ public: AbortCallback abortCallback); void clean(); + void waitForFinished(); private: enum class RequestType { Image, Icon }; @@ -99,6 +100,9 @@ private: ImageCacheGeneratorInterface &generator, TimeStampProviderInterface &timeStampProvider); +private: + void wait(); + private: std::vector m_entries; mutable std::mutex m_mutex; diff --git a/tests/unit/unittest/imagecache-test.cpp b/tests/unit/unittest/imagecache-test.cpp index f3f2c825180..a4365936201 100644 --- a/tests/unit/unittest/imagecache-test.cpp +++ b/tests/unit/unittest/imagecache-test.cpp @@ -319,4 +319,27 @@ TEST_F(ImageCache, AfterCleanNewJobsWorks) notification.wait(); } +TEST_F(ImageCache, WaitForFinished) +{ + ON_CALL(mockStorage, fetchImage(_, _)) + .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true})); + cache.requestImage("/path/to/Component1.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction()); + cache.requestImage("/path/to/Component2.qml", + mockCaptureCallback.AsStdFunction(), + mockAbortCallback.AsStdFunction()); + + EXPECT_CALL(mockCaptureCallback, Call(_)).Times(2); + + cache.waitForFinished(); +} + +TEST_F(ImageCache, WaitForFinishedInGenerator) +{ + EXPECT_CALL(mockGenerator, waitForFinished()); + + cache.waitForFinished(); +} + } // namespace diff --git a/tests/unit/unittest/imagecachegenerator-test.cpp b/tests/unit/unittest/imagecachegenerator-test.cpp index 3b183d00672..e5749041e1b 100644 --- a/tests/unit/unittest/imagecachegenerator-test.cpp +++ b/tests/unit/unittest/imagecachegenerator-test.cpp @@ -247,4 +247,23 @@ TEST_F(ImageCacheGenerator, CleanIsCallingAbortCallback) waitInThread.notify(); } +TEST_F(ImageCacheGenerator, WaitForFinished) +{ + ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto captureCallback, auto) { + captureCallback(QImage{image1}); + }); + generator.generateImage("name", + {11}, + imageCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); + generator.generateImage("name2", + {11}, + imageCallbackMock.AsStdFunction(), + abortCallbackMock.AsStdFunction()); + + EXPECT_CALL(imageCallbackMock, Call(_)).Times(2); + + generator.waitForFinished(); +} + } // namespace diff --git a/tests/unit/unittest/mockimagecachegenerator.h b/tests/unit/unittest/mockimagecachegenerator.h index ffe8d9c7097..d76ef8f8a4a 100644 --- a/tests/unit/unittest/mockimagecachegenerator.h +++ b/tests/unit/unittest/mockimagecachegenerator.h @@ -40,4 +40,5 @@ public: AbortCallback &&abortCallback), (override)); MOCK_METHOD(void, clean, (), (override)); + MOCK_METHOD(void, waitForFinished, (), (override)); };