From a3701093f6cd1d37bca79db67dc8840b2f304a33 Mon Sep 17 00:00:00 2001 From: Xottab-DUTY Date: Sat, 18 Jan 2025 14:27:49 +0300 Subject: [PATCH] xrCore/Threading/TaskManager.cpp: replace std::condition_variable with Event std::condition_variable serves different purpose and event exactly fits our use case. 1. We had used std::condition_variable::wait wrongly as all threads must lock the same mutex and this requirement wasn't satisfied. 2. Previous implementation (before std::condition_variable) was using an event per each worker thread. I only now figured out that we can just use one event. Fixes #1731. --- src/xrCore/Threading/TaskManager.cpp | 10 ++++------ src/xrCore/Threading/TaskManager.hpp | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/xrCore/Threading/TaskManager.cpp b/src/xrCore/Threading/TaskManager.cpp index b1a6e1d50b4..88ba116c5aa 100644 --- a/src/xrCore/Threading/TaskManager.cpp +++ b/src/xrCore/Threading/TaskManager.cpp @@ -140,7 +140,6 @@ struct TaskWorkerStats class TaskWorker : public TaskQueue, public TaskWorkerStats { public: - std::mutex mutex; fast_lc16 random{ this }; size_t id { size_t(-1) }; } static thread_local s_tl_worker; @@ -179,7 +178,7 @@ TaskManager::~TaskManager() UnregisterThisThreadAsWorker(); while (!workers.empty()) { - newWorkArrived.notify_all(); + newWorkArrived.Set(); SDL_PumpEvents(); Sleep(0); } @@ -242,10 +241,9 @@ void TaskManager::TaskWorkerStart() SetThreadStatus(false); { - std::unique_lock lck(s_tl_worker.mutex); do { - newWorkArrived.wait(lck); // spurious wakeups allowed + newWorkArrived.Wait(); } while (shouldPause.load(std::memory_order_consume)); } SetThreadStatus(true); @@ -277,7 +275,7 @@ Task* TaskManager::TryToSteal() const if (auto* task = other->steal()) { if (!other->empty()) - newWorkArrived.notify_all(); + newWorkArrived.Set(); return task; } --steal_attempts; @@ -294,7 +292,7 @@ Task* TaskManager::AllocateTask() noexcept void TaskManager::PushTask(Task& task) noexcept { s_tl_worker.push(&task); - newWorkArrived.notify_one(); + newWorkArrived.Set(); ++s_tl_worker.pushedTasks; } diff --git a/src/xrCore/Threading/TaskManager.hpp b/src/xrCore/Threading/TaskManager.hpp index 60780220ed0..fa87dfb393b 100644 --- a/src/xrCore/Threading/TaskManager.hpp +++ b/src/xrCore/Threading/TaskManager.hpp @@ -16,9 +16,9 @@ #pragma once #include "Task.hpp" +#include "Event.hpp" #include -#include #include class TaskWorker; @@ -30,7 +30,7 @@ class XRCORE_API TaskManager final xr_vector workerThreads; std::mutex workersLock; - inline static std::condition_variable newWorkArrived; + inline static Event newWorkArrived; std::atomic_size_t activeWorkersCount{}; std::atomic_bool shouldPause{};