[vlc-devel] [PATCH] qt: medialib: add async task handle

Pierre Lamot pierre at videolabs.io
Wed Jan 6 15:55:36 UTC 2021


Hi, OK for the patch,

some nits bellow.

On 2021-01-06 15:55, Romain Vimont wrote:
> Use a smart pointer to "abandon" an AsyncTask using RAII. This avoids 
> to
> forget to call abandon() on client destruction.
> ---
>  modules/gui/qt/util/asynctask.hpp | 22 +++++++++++++++++++
>  modules/gui/qt/util/listcache.hpp | 36 +++++++++----------------------
>  2 files changed, 32 insertions(+), 26 deletions(-)
> 
> diff --git a/modules/gui/qt/util/asynctask.hpp
> b/modules/gui/qt/util/asynctask.hpp
> index fa4a6d3b2c..81fcc54022 100644
> --- a/modules/gui/qt/util/asynctask.hpp
> +++ b/modules/gui/qt/util/asynctask.hpp
> @@ -128,6 +128,9 @@
>   * to declare that it won't use it anymore (and don't want the 
> result). When
>   * both conditions are met, the task is deleted via 
> `QObject::deleteLater()`.
>   *
> + * For convenience, a `TaskHandle` smart pointer is provided to call
> + * `abandon()` using RAII.
> + *
>   * The task result is provided via a separate method `takeResult()` 
> instead of
>   * a slot parameter, because otherwise, Qt would require its type to 
> be:
>   *  - non-template (like `std::vector<T>`),
> @@ -243,4 +246,23 @@ private:
>      AsyncTask<T> *m_task;
>  };
> 
> +template <typename T>
> +struct TaskDeleter
> +{
> +    void operator()(T *task) { task->abandon(); }
> +};
> +
> +/**
> + * Task handle to abandon() a task using RAII
> + *
> + * It behaves like a unique_ptr, but its deleter calls 
> AsyncTask<T>::abandon(),
> + * which indicates that the client cancels the task and requests 
> deletion when
> + * possible.
> + *
> + * The actual deletion may happen later (when the runnable also 
> finished its
> + * work).
> + */
> +template <typename T>
> +using TaskHandle = std::unique_ptr<T, TaskDeleter<T>>;
> +
>  #endif
> diff --git a/modules/gui/qt/util/listcache.hpp
> b/modules/gui/qt/util/listcache.hpp
> index e92b7d84df..20fa510832 100644
> --- a/modules/gui/qt/util/listcache.hpp
> +++ b/modules/gui/qt/util/listcache.hpp
> @@ -115,7 +115,6 @@ public:
>          : m_threadPool(threadPool)
>          , m_loader(loader)
>          , m_chunkSize(chunkSize) {}
> -    ~ListCache();
> 
>      /**
>       * Return the item at specified index
> @@ -167,19 +166,10 @@ private:
>      bool m_countRequested = false;
>      MLRange m_lastRangeRequested;
> 
> -    LoadTask<T> *m_loadTask = nullptr;
> -    CountTask<T> *m_countTask = nullptr;
> +    TaskHandle<LoadTask<T>> m_loadTask;
> +    TaskHandle<CountTask<T>> m_countTask;
>  };
> 
> -template <typename T>
> -ListCache<T>::~ListCache()
> -{
> -    if (m_countTask)
> -        m_countTask->abandon();
> -    if (m_loadTask)
> -        m_loadTask->abandon();
> -}
> -
>  template <typename T>
>  const T *ListCache<T>::get(size_t index) const
>  {
> @@ -248,8 +238,8 @@ void ListCache<T>::asyncCount()
>  {
>      assert(!m_countTask);
> 
> -    m_countTask = new CountTask<T>(m_loader);
> -    connect(m_countTask, &BaseAsyncTask::result,
> +    m_countTask.reset(new CountTask<T>(m_loader));

maybe use std::make_unique

> +    connect(&*m_countTask, &BaseAsyncTask::result,
>              this, &ListCache<T>::onCountResult);

m_countTask.get() directly gives you the underlying address.

>      m_countRequested = true;
>      m_countTask->start(m_threadPool);
> @@ -259,15 +249,14 @@ template <typename T>
>  void ListCache<T>::onCountResult()
>  {
>      CountTask<T> *task = static_cast<CountTask<T> *>(sender());
> -    assert(task == m_countTask);
> +    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;
> +    m_countTask.reset();
>  }
> 
>  template <typename T>
> @@ -298,12 +287,8 @@ private:
>  template <typename T>
>  void ListCache<T>::asyncLoad(size_t offset, size_t count)
>  {
> -    if (m_loadTask)
> -        /* Cancel any current pending task */
> -        m_loadTask->abandon();
> -
> -    m_loadTask = new LoadTask<T>(m_loader, offset, count);
> -    connect(m_loadTask, &BaseAsyncTask::result,
> +    m_loadTask.reset(new LoadTask<T>(m_loader, offset, count));
> +    connect(&*m_loadTask, &BaseAsyncTask::result,
>              this, &ListCache<T>::onLoadResult);
>      m_lastRangeRequested = { offset, count };
>      m_loadTask->start(m_threadPool);
> @@ -313,15 +298,14 @@ template <typename T>
>  void ListCache<T>::onLoadResult()
>  {
>      LoadTask<T> *task = static_cast<LoadTask<T> *>(sender());
> -    assert(task == m_loadTask);
> +    assert(task == &*m_loadTask);
> 
>      m_offset = task->m_offset;
>      m_list = task->takeResult();
>      if (m_list.size())
>          emit localDataChanged(m_offset, m_list.size());
> 
> -    task->abandon();
> -    m_loadTask = nullptr;
> +    m_loadTask.reset();
>  }
> 
>  #endif


More information about the vlc-devel mailing list