Switch env lock to fair mutex implementation

This commit is contained in:
sfan5 2024-09-15 22:16:05 +02:00
parent 0220d0d492
commit 5f308deb50
2 changed files with 49 additions and 2 deletions

@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/metricsbackend.h" #include "util/metricsbackend.h"
#include "serverenvironment.h" #include "serverenvironment.h"
#include "server/clientiface.h" #include "server/clientiface.h"
#include "threading/ordered_mutex.h"
#include "chatmessage.h" #include "chatmessage.h"
#include "sound.h" #include "sound.h"
#include "translation.h" #include "translation.h"
@ -430,7 +431,7 @@ public:
EnvAutoLock(Server *server): m_lock(server->m_env_mutex) {} EnvAutoLock(Server *server): m_lock(server->m_env_mutex) {}
private: private:
MutexAutoLock m_lock; std::lock_guard<ordered_mutex> m_lock;
}; };
protected: protected:
@ -608,7 +609,7 @@ private:
*/ */
// Environment mutex (envlock) // Environment mutex (envlock)
std::mutex m_env_mutex; ordered_mutex m_env_mutex;
// World directory // World directory
std::string m_path_world; std::string m_path_world;

@ -0,0 +1,46 @@
// Minetest
// SPDX-License-Identifier: LGPL-2.1-or-later
#pragma once
#include <cstdint>
#include <condition_variable>
/*
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;
};