From 5f308deb50133e4d42ec2920cd98c1d3797fa58f Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 15 Sep 2024 22:16:05 +0200 Subject: [PATCH] Switch env lock to fair mutex implementation --- src/server.h | 5 ++-- src/threading/ordered_mutex.h | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/threading/ordered_mutex.h diff --git a/src/server.h b/src/server.h index 51d52d443..6b48d929d 100644 --- a/src/server.h +++ b/src/server.h @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/metricsbackend.h" #include "serverenvironment.h" #include "server/clientiface.h" +#include "threading/ordered_mutex.h" #include "chatmessage.h" #include "sound.h" #include "translation.h" @@ -430,7 +431,7 @@ public: EnvAutoLock(Server *server): m_lock(server->m_env_mutex) {} private: - MutexAutoLock m_lock; + std::lock_guard m_lock; }; protected: @@ -608,7 +609,7 @@ private: */ // Environment mutex (envlock) - std::mutex m_env_mutex; + ordered_mutex m_env_mutex; // World directory std::string m_path_world; diff --git a/src/threading/ordered_mutex.h b/src/threading/ordered_mutex.h new file mode 100644 index 000000000..f7fb4d309 --- /dev/null +++ b/src/threading/ordered_mutex.h @@ -0,0 +1,46 @@ +// Minetest +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include +#include + +/* + Fair mutex based on ticketing approach. + Satisfies `Mutex` C++11 requirements. +*/ +class ordered_mutex { +public: + ordered_mutex() : next_ticket(0), counter(0) {} + + void lock() + { + std::unique_lock autolock(cv_lock); + const auto ticket = next_ticket++; + cv.wait(autolock, [&] { return counter == ticket; }); + } + + bool try_lock() + { + std::lock_guard autolock(cv_lock); + if (counter != next_ticket) + return false; + next_ticket++; + return true; + } + + void unlock() + { + { + std::lock_guard autolock(cv_lock); + counter++; + } + cv.notify_all(); // intentionally outside lock + } + +private: + std::condition_variable cv; + std::mutex cv_lock; + uint_fast32_t next_ticket, counter; +};