From d687a94408307794532e76a3e19d21dab9aa2539 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 23 Nov 2025 18:46:29 -0600 Subject: [PATCH 1/6] Common:: Add DummyMutex and make WorkQueueThreadBase use it. --- Source/Core/Common/Mutex.h | 14 ++++++++++++++ Source/Core/Common/WorkQueueThread.h | 16 ++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Source/Core/Common/Mutex.h b/Source/Core/Common/Mutex.h index 22aebd08b1..fbb7c1a4c7 100644 --- a/Source/Core/Common/Mutex.h +++ b/Source/Core/Common/Mutex.h @@ -48,4 +48,18 @@ using AtomicMutex = detail::AtomicMutexBase; // Very fast to lock and unlock when uncontested (~3x faster than std::mutex). using SpinMutex = detail::AtomicMutexBase; +// This "mutex" class provides no actual thread synchronization. +// It has a std::shared_mutex interface only to be compatible with standard locks. +// Useful when template parameters can determine that a mutex is not actually needed. +struct DummyMutex +{ + constexpr void lock() {} + constexpr bool try_lock() { return true; } + constexpr void unlock() {} + + constexpr void lock_shared() {} + constexpr bool try_lock_shared() { return true; } + constexpr void unlock_shared() {} +}; + } // namespace Common diff --git a/Source/Core/Common/WorkQueueThread.h b/Source/Core/Common/WorkQueueThread.h index 8816ddda16..6a5eaa73b2 100644 --- a/Source/Core/Common/WorkQueueThread.h +++ b/Source/Core/Common/WorkQueueThread.h @@ -10,6 +10,7 @@ #include #include "Common/Event.h" +#include "Common/Mutex.h" #include "Common/SPSCQueue.h" #include "Common/Thread.h" @@ -128,19 +129,7 @@ private: m_commands.Clear(); } - auto GetLockGuard() - { - struct DummyLockGuard - { - // Silences unused variable warning. - ~DummyLockGuard() { void(); } - }; - - if constexpr (IsSingleProducer) - return DummyLockGuard{}; - else - return std::lock_guard{m_mutex}; - } + auto GetLockGuard() { return std::lock_guard{m_mutex}; } bool IsRunning() { return m_thread.joinable(); } @@ -177,7 +166,6 @@ private: Common::WaitableSPSCQueue m_commands; Common::Event m_event; - using DummyMutex = std::type_identity; using ProducerMutex = std::conditional_t; ProducerMutex m_mutex; }; From 2a9038c74664ffc0ea29bd248aa40e0e71a8bf31 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 23 Nov 2025 18:47:49 -0600 Subject: [PATCH 2/6] Common: Make a void-returning MoveOnlyFunction able to accept a non-void-returning function object and just drop the return value. std::function behaves this way. --- Source/Core/Common/Functional.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Functional.h b/Source/Core/Common/Functional.h index 7f96664041..1d21cdce05 100644 --- a/Source/Core/Common/Functional.h +++ b/Source/Core/Common/Functional.h @@ -45,7 +45,18 @@ private: struct Func : FuncBase { explicit Func(F&& f) : func{std::forward(f)} {} - result_type Invoke(Args... args) override { return func(std::forward(args)...); } + result_type Invoke(Args... args) override + { +// TODO: Remove fallback when we can require Clang 17. +#if defined(__cpp_lib_invoke_r) && (__cpp_lib_invoke_r >= 202106L) + return std::invoke_r(func, std::forward(args)...); +#else + if constexpr (std::is_void_v) + func(std::forward(args)...); + else + return func(std::forward(args)...); +#endif + } std::decay_t func; }; From dfabdbd24246353ed276ebb4176ba9d938c4a533 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 23 Nov 2025 18:58:43 -0600 Subject: [PATCH 3/6] Common: Make WorkQueueThread and AsyncWorkThread use MoveOnlyFunction so non-copyable function objects can be used. --- Source/Core/Common/WorkQueueThread.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/Core/Common/WorkQueueThread.h b/Source/Core/Common/WorkQueueThread.h index 6a5eaa73b2..3c5e2265af 100644 --- a/Source/Core/Common/WorkQueueThread.h +++ b/Source/Core/Common/WorkQueueThread.h @@ -10,6 +10,7 @@ #include #include "Common/Event.h" +#include "Common/Functional.h" #include "Common/Mutex.h" #include "Common/SPSCQueue.h" #include "Common/Thread.h" @@ -18,12 +19,10 @@ namespace Common { namespace detail { -template +template class WorkQueueThreadBase final { public: - using FunctionType = std::function; - WorkQueueThreadBase() = default; WorkQueueThreadBase(std::string name, FunctionType function) { @@ -100,7 +99,7 @@ public: } private: - using CommandFunction = std::function; + using CommandFunction = MoveOnlyFunction; // Blocking. void RunCommand(CommandFunction cmd) @@ -171,11 +170,11 @@ private: }; // A WorkQueueThread-like class that takes functions to invoke. -template