diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 5a38894191..d711febbf1 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1736,22 +1736,6 @@ bool thread_ctrl::_wait_for(u64 usec) { auto _this = g_tls_this_thread; - struct half_lock - { - shared_mutex& ref; - - void lock() - { - // Used to avoid additional lock + unlock - } - - void unlock() - { - ref.unlock(); - } - } - _lock{_this->m_mutex}; - do { // Mutex is unlocked at the start and after the waiting @@ -1772,7 +1756,6 @@ bool thread_ctrl::_wait_for(u64 usec) return false; } - // Lock (semaphore) _this->m_mutex.lock(); // Double-check the value @@ -1791,7 +1774,7 @@ bool thread_ctrl::_wait_for(u64 usec) } } } - while (_this->m_cond.wait(_lock, std::exchange(usec, usec > cond_variable::max_timeout ? -1 : 0))); + while (_this->m_cond.wait_unlock(std::exchange(usec, usec > cond_variable::max_timeout ? -1 : 0), _this->m_mutex)); // Timeout return false; diff --git a/Utilities/cond.h b/Utilities/cond.h index 99eb82b83f..a083dd39f1 100644 --- a/Utilities/cond.h +++ b/Utilities/cond.h @@ -2,6 +2,7 @@ #include "types.h" #include "Atomic.h" +#include // Lightweight condition variable class cond_variable @@ -32,6 +33,15 @@ public: return res; } + // Unlock all specified objects but don't lock them again + template + bool wait_unlock(u64 usec_timeout, Locks&&... locks) + { + const u32 _old = m_value.fetch_add(1); // Increment waiter counter + (..., std::forward(locks).unlock()); + return imp_wait(_old, usec_timeout); + } + // Wake one thread void notify_one() noexcept {