forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
|
Reference in New Issue
Block a user