Fix problems with global locks

* Aquire the mutex before setting `m_exclusivelyOwned = false`; otherwise
  it might be set after `lock()` has checked it but before `lock()` has
  entered `wait()` leading to a deadlock
* Check state again after `wait()` because it may also be unblocked
  "spuriously" so it isn't guaranteed that the state will have actually
  changed after unblocking
This commit is contained in:
Martchus 2022-01-25 22:49:20 +01:00
parent 218dfecf56
commit d4d187463a
1 changed files with 4 additions and 2 deletions

View File

@ -32,7 +32,7 @@ private:
inline void GlobalSharedMutex::lock() inline void GlobalSharedMutex::lock()
{ {
auto lock = std::unique_lock<std::mutex>(m_mutex); auto lock = std::unique_lock<std::mutex>(m_mutex);
if (m_sharedOwners || m_exclusivelyOwned) { while (m_sharedOwners || m_exclusivelyOwned) {
m_cv.wait(lock); m_cv.wait(lock);
} }
m_exclusivelyOwned = true; m_exclusivelyOwned = true;
@ -50,14 +50,16 @@ inline bool GlobalSharedMutex::try_lock()
inline void GlobalSharedMutex::unlock() inline void GlobalSharedMutex::unlock()
{ {
auto lock = std::unique_lock<std::mutex>(m_mutex);
m_exclusivelyOwned = false; m_exclusivelyOwned = false;
lock.unlock();
m_cv.notify_one(); m_cv.notify_one();
} }
inline void GlobalSharedMutex::lock_shared() inline void GlobalSharedMutex::lock_shared()
{ {
auto lock = std::unique_lock<std::mutex>(m_mutex); auto lock = std::unique_lock<std::mutex>(m_mutex);
if (m_exclusivelyOwned) { while (m_exclusivelyOwned) {
m_cv.wait(lock); m_cv.wait(lock);
} }
++m_sharedOwners; ++m_sharedOwners;