[vlc-devel] [PATCH v2 12/13] qt: medialib: make cache count() asynchronous

Romain Vimont rom1v at videolabs.io
Thu Nov 26 17:10:44 CET 2020


Make the list cache use an async task for executing the count() call.
---
 modules/gui/qt/medialibrary/mlbasemodel.cpp | 13 +++++
 modules/gui/qt/medialibrary/mlbasemodel.hpp |  7 ++-
 modules/gui/qt/util/listcache.hpp           | 62 ++++++++++++++++++++-
 3 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/modules/gui/qt/medialibrary/mlbasemodel.cpp b/modules/gui/qt/medialibrary/mlbasemodel.cpp
index 24d1362078..65dc1939e1 100644
--- a/modules/gui/qt/medialibrary/mlbasemodel.cpp
+++ b/modules/gui/qt/medialibrary/mlbasemodel.cpp
@@ -66,6 +66,19 @@ void MLBaseModel::onResetRequested()
     endResetModel();
 }
 
+void MLBaseModel::onLocalSizeAboutToBeChanged(size_t size)
+{
+    (void) size;
+    beginResetModel();
+}
+
+void MLBaseModel::onLocalSizeChanged(size_t size)
+{
+    (void) size;
+    endResetModel();
+    emit countChanged(size);
+}
+
 void MLBaseModel::onLocalDataChanged(size_t offset, size_t count)
 {
     assert(count);
diff --git a/modules/gui/qt/medialibrary/mlbasemodel.hpp b/modules/gui/qt/medialibrary/mlbasemodel.hpp
index 09e863961b..3868a34651 100644
--- a/modules/gui/qt/medialibrary/mlbasemodel.hpp
+++ b/modules/gui/qt/medialibrary/mlbasemodel.hpp
@@ -70,6 +70,8 @@ signals:
 
 protected slots:
     void onResetRequested();
+    void onLocalSizeAboutToBeChanged(size_t size);
+    void onLocalSizeChanged(size_t size);
     void onLocalDataChanged(size_t index, size_t count);
 
 private:
@@ -222,11 +224,14 @@ protected:
         auto &threadPool = m_mediaLib->threadPool();
         auto loader = createLoader();
         m_cache.reset(new ListCache<std::unique_ptr<T>>(threadPool, loader));
+        connect(&*m_cache, &BaseListCache::localSizeAboutToBeChanged,
+                this, &MLBaseModel::onLocalSizeAboutToBeChanged);
+        connect(&*m_cache, &BaseListCache::localSizeChanged,
+                this, &MLBaseModel::onLocalSizeChanged);
         connect(&*m_cache, &BaseListCache::localDataChanged,
                 this, &MLBaseModel::onLocalDataChanged);
 
         m_cache->initCount();
-        emit countChanged( static_cast<unsigned int>(m_cache->count()) );
     }
 
     void invalidateCache()
diff --git a/modules/gui/qt/util/listcache.hpp b/modules/gui/qt/util/listcache.hpp
index c476ee18d3..08722256d9 100644
--- a/modules/gui/qt/util/listcache.hpp
+++ b/modules/gui/qt/util/listcache.hpp
@@ -72,12 +72,20 @@ class BaseListCache : public QObject
     Q_OBJECT
 
 signals:
+    /* useful for signaling QAbstractItemModel::modelAboutToBeReset() */
+    void localSizeAboutToBeChanged(size_t size);
+
+    void localSizeChanged(size_t size);
     void localDataChanged(size_t index, size_t count);
 
 protected slots:
     virtual void onLoadResult() = 0;
+    virtual void onCountResult() = 0;
 };
 
+template <typename T>
+class CountTask;
+
 template <typename T>
 class LoadTask;
 
@@ -147,9 +155,11 @@ public:
     void refer(size_t index);
 
 private:
+    void asyncLoad(size_t offset, size_t count);
     void onLoadResult() override;
 
-    void asyncLoad(size_t offset, size_t count);
+    void asyncCount();
+    void onCountResult() override;
 
     QThreadPool &m_threadPool;
     /* Ownershipshared between this cache and the runnable spawned to execute
@@ -161,14 +171,18 @@ private:
     ssize_t m_total_count = COUNT_UNINITIALIZED;
     size_t m_offset = 0;
 
+    bool m_countRequested = false;
     MLRange m_lastRangeRequested;
 
     LoadTask<T> *m_loadTask = nullptr;
+    CountTask<T> *m_countTask = nullptr;
 };
 
 template <typename T>
 ListCache<T>::~ListCache()
 {
+    if (m_countTask)
+        m_countTask->abandon();
     if (m_loadTask)
         m_loadTask->abandon();
 }
@@ -192,8 +206,8 @@ ssize_t ListCache<T>::count() const
 template <typename T>
 void ListCache<T>::initCount()
 {
-    assert(m_total_count == COUNT_UNINITIALIZED);
-    m_total_count = static_cast<ssize_t>(m_loader->count());
+    assert(!m_countRequested);
+    asyncCount();
 }
 
 template <typename T>
@@ -221,6 +235,48 @@ void ListCache<T>::refer(size_t index)
     }
 }
 
+template <typename T>
+class CountTask : public AsyncTask<size_t>
+{
+public:
+    CountTask(QSharedPointer<ListCacheLoader<T>> loader) : m_loader(loader) {}
+
+    size_t execute() override
+    {
+        return m_loader->count();
+    }
+
+private:
+    QSharedPointer<ListCacheLoader<T>> m_loader;
+};
+
+template <typename T>
+void ListCache<T>::asyncCount()
+{
+    assert(!m_countTask);
+
+    m_countTask = new CountTask<T>(m_loader);
+    connect(m_countTask, &BaseAsyncTask::result,
+            this, &BaseListCache::onCountResult);
+    m_countRequested = true;
+    m_countTask->start(m_threadPool);
+}
+
+template <typename T>
+void ListCache<T>::onCountResult()
+{
+    CountTask<T> *task = static_cast<CountTask<T> *>(sender());
+    assert(task == m_countTask);
+
+    m_offset = 0;
+    m_list.clear();
+    m_total_count = static_cast<ssize_t>(task->takeResult());
+    emit localSizeChanged(m_total_count);
+
+    task->abandon();
+    m_countTask = nullptr;
+}
+
 template <typename T>
 class LoadTask : public AsyncTask<std::vector<T>>
 {
-- 
2.29.2



More information about the vlc-devel mailing list