QmlDesigner: Improve task queue

The abort callbacks does not need any lock. It even can lead to a
deadlock if they call back. And a thread was always newly started.

Change-Id: I0e25b66bb3647aae16113628487acaa4c7377819
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2023-09-01 16:03:21 +02:00
parent 37c0737844
commit e0c129d4b1

View File

@@ -13,18 +13,15 @@ namespace QmlDesigner {
template<typename Task, typename DispatchCallback, typename ClearCallback> template<typename Task, typename DispatchCallback, typename ClearCallback>
class TaskQueue class TaskQueue
{ {
using Tasks = std::deque<Task>;
public: public:
TaskQueue(DispatchCallback dispatchCallback, ClearCallback clearCallback) TaskQueue(DispatchCallback dispatchCallback, ClearCallback clearCallback)
: m_dispatchCallback(std::move(dispatchCallback)) : m_dispatchCallback(std::move(dispatchCallback))
, m_clearCallback(std::move(clearCallback)) , m_clearCallback(std::move(clearCallback))
{} {}
~TaskQueue() ~TaskQueue() { destroy(); }
{
auto lock = clearTasks();
stopThread(std::move(lock));
joinThread();
}
template<typename... Arguments> template<typename... Arguments>
void addTask(Arguments &&...arguments) void addTask(Arguments &&...arguments)
@@ -39,9 +36,24 @@ public:
m_condition.notify_all(); m_condition.notify_all();
} }
void clean() { clearTasks(); } void clean()
{
Tasks oldTasks;
{
std::unique_lock lock{m_mutex};
std::swap(m_tasks, oldTasks);
}
clearTasks(oldTasks);
}
private: private:
void destroy()
{
stopThread();
joinThread();
clearTasks(m_tasks);
}
[[nodiscard]] std::tuple<std::unique_lock<std::mutex>, bool> waitForTasks() [[nodiscard]] std::tuple<std::unique_lock<std::mutex>, bool> waitForTasks()
{ {
using namespace std::literals::chrono_literals; using namespace std::literals::chrono_literals;
@@ -80,7 +92,7 @@ private:
return; return;
if (m_backgroundThread.joinable()) if (m_backgroundThread.joinable())
m_backgroundThread.join(); return;
m_sleeping = false; m_sleeping = false;
@@ -95,20 +107,16 @@ private:
}}; }};
} }
std::unique_lock<std::mutex> clearTasks() void clearTasks(Tasks &tasks)
{ {
std::unique_lock lock{m_mutex}; for (Task &task : tasks)
for (Task &task : m_tasks)
m_clearCallback(task); m_clearCallback(task);
m_tasks.clear();
return lock;
} }
void stopThread(std::unique_lock<std::mutex> lock) void stopThread()
{ {
{ {
auto l = std::move(lock); std::unique_lock lock{m_mutex};
m_finishing = true; m_finishing = true;
} }
m_condition.notify_all(); m_condition.notify_all();
@@ -121,7 +129,7 @@ private:
} }
private: private:
std::deque<Task> m_tasks; Tasks m_tasks;
std::mutex m_mutex; std::mutex m_mutex;
std::condition_variable m_condition; std::condition_variable m_condition;
std::thread m_backgroundThread; std::thread m_backgroundThread;