Remove Mutex class, replace with std::mutex

Also removes unused Condition class
This commit is contained in:
brainiac 2025-12-28 02:11:13 -08:00
parent 4693b11cb2
commit e12c52a66a
20 changed files with 118 additions and 545 deletions

View File

@ -7,7 +7,6 @@ set(common_sources
classes.cpp
cli/eqemu_command_handler.cpp
compression.cpp
condition.cpp
content/world_content_service.cpp
crash.cpp
crc16.cpp
@ -61,7 +60,6 @@ set(common_sources
memory_mapped_file.cpp
misc.cpp
misc_functions.cpp
mutex.cpp
mysql_request_result.cpp
mysql_request_row.cpp
mysql_stmt.cpp
@ -548,7 +546,6 @@ set(common_headers
cli/terminal_color.hpp
classes.h
compression.h
condition.h
content/world_content_service.h
crash.h
crc16.h
@ -627,7 +624,6 @@ set(common_headers
memory_mapped_file.h
misc.h
misc_functions.h
mutex.h
mysql_request_result.h
mysql_request_row.h
mysql_stmt.h

View File

@ -1,146 +0,0 @@
/* EQEmu: EQEmulator
Copyright (C) 2001-2026 EQEmu Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "condition.h"
#ifdef _WINDOWS
Condition::Condition()
{
m_events[SignalEvent] = CreateEvent (nullptr, // security
FALSE, // is auto-reset event?
FALSE, // is signaled initially?
nullptr); // name
m_events[BroadcastEvent] = CreateEvent (nullptr, // security
TRUE, // is auto-reset event?
FALSE, // is signaled initially?
nullptr); // name
m_waiters = 0;
InitializeCriticalSection(&CSMutex);
}
Condition::~Condition()
{
DeleteCriticalSection(&CSMutex);
CloseHandle(m_events[SignalEvent]);
CloseHandle(m_events[BroadcastEvent]);
}
void Condition::Signal()
{
EnterCriticalSection(&CSMutex);
if(m_waiters > 0)
SetEvent(m_events[SignalEvent]);
LeaveCriticalSection(&CSMutex);
}
void Condition::SignalAll()
{
EnterCriticalSection(&CSMutex);
if(m_waiters > 0)
SetEvent(m_events[BroadcastEvent]);
LeaveCriticalSection(&CSMutex);
}
void Condition::Wait()
{
EnterCriticalSection(&CSMutex);
m_waiters++;
LeaveCriticalSection(&CSMutex);
int result = WaitForMultipleObjects (_eventCount, m_events, FALSE, INFINITE);
EnterCriticalSection(&CSMutex);
m_waiters--;
//see if we are the last person waiting on the condition, and there was a broadcast
//if so, we need to reset the broadcast event.
if(m_waiters == 0 && result == (WAIT_OBJECT_0+BroadcastEvent))
ResetEvent(m_events[BroadcastEvent]);
LeaveCriticalSection(&CSMutex);
}
#else
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
Condition::Condition()
{
pthread_cond_init(&cond,nullptr);
pthread_mutex_init(&mutex,nullptr);
}
void Condition::Signal()
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void Condition::SignalAll()
{
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
void Condition::Wait()
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
pthread_mutex_unlock(&mutex);
}
/*
I commented this specifically because I think it might be very
difficult to write a windows counterpart to it, so I would like
to discourage its use until we can confirm that it can be reasonably
implemented on windows.
bool Condition::TimedWait(unsigned long usec)
{
struct timeval now;
struct timespec timeout;
int retcode=0;
pthread_mutex_lock(&mutex);
gettimeofday(&now,nullptr);
now.tv_usec+=usec;
timeout.tv_sec = now.tv_sec + (now.tv_usec/1000000);
timeout.tv_nsec = (now.tv_usec%1000000) *1000;
//cout << "now=" << now.tv_sec << "."<<now.tv_usec << endl;
//cout << "timeout=" << timeout.tv_sec << "."<<timeout.tv_nsec << endl;
retcode=pthread_cond_timedwait(&cond,&mutex,&timeout);
pthread_mutex_unlock(&mutex);
return retcode!=ETIMEDOUT;
}
*/
Condition::~Condition()
{
pthread_mutex_lock(&mutex);
pthread_cond_destroy(&cond);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
}
#endif

View File

@ -1,51 +0,0 @@
/* EQEmu: EQEmulator
Copyright (C) 2001-2026 EQEmu Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/mutex.h"
#include "common/platform/posix/include_pthreads.h"
#include "common/platform/win/include_windows.h"
//Sombody, someday needs to figure out how to implement a condition
//system on windows...
class Condition {
private:
#ifdef WIN32
enum {
SignalEvent = 0,
BroadcastEvent,
_eventCount
};
HANDLE m_events[_eventCount];
uint32 m_waiters;
CRITICAL_SECTION CSMutex;
#else
pthread_cond_t cond;
pthread_mutex_t mutex;
#endif
public:
Condition();
void Signal();
void SignalAll();
void Wait();
// bool TimedWait(unsigned long usec);
~Condition();
};

View File

@ -728,7 +728,7 @@ bool Database::LoadVariables()
return true;
}
LockMutex lock(&Mvarcache);
std::scoped_lock lock(Mvarcache);
for (const auto& e : l) {
varcache.last_update = std::time(nullptr);
@ -747,7 +747,7 @@ bool Database::LoadVariables()
bool Database::GetVariable(const std::string& name, std::string& value)
{
LockMutex lock(&Mvarcache);
std::scoped_lock lock(Mvarcache);
if (name.empty()) {
return false;

View File

@ -20,13 +20,12 @@
#include "common/dbcore.h"
#include "common/eq_packet_structs.h"
#include "common/eqemu_logsys.h"
#include "common/linked_list.h"
#include "common/types.h"
#include <cmath>
#include <map>
#include <mutex>
#include <string>
#include <vector>
#include <map>
#define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF
@ -265,7 +264,7 @@ public:
uint64_t GetNextTableId(const std::string& table_name);
private:
Mutex Mvarcache;
std::mutex Mvarcache;
VarCache_Struct varcache;
/* Groups, utility methods. */

View File

@ -33,17 +33,9 @@
#endif
DBcore::DBcore()
: mysql(mysql_init(nullptr))
, m_mutex(std::make_shared<std::mutex>())
{
mysql = mysql_init(nullptr);
mysqlOwner = true;
pHost = nullptr;
pUser = nullptr;
pPassword = nullptr;
pDatabase = nullptr;
pCompress = false;
pSSL = false;
pStatus = Closed;
m_mutex = new Mutex;
}
DBcore::~DBcore()
@ -56,20 +48,17 @@ DBcore::~DBcore()
if (mysqlOwner) {
mysql_close(mysql);
}
safe_delete_array(pHost);
safe_delete_array(pUser);
safe_delete_array(pPassword);
safe_delete_array(pDatabase);
}
// Sends the MySQL server a keepalive
void DBcore::ping()
{
if (!m_mutex->trylock()) {
if (!m_mutex->try_lock())
{
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
return;
}
mysql_ping(mysql);
m_mutex->unlock();
}
@ -92,7 +81,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
BenchTimer timer;
timer.reset();
LockMutex lock(m_mutex);
std::scoped_lock lock(*m_mutex);
// Reconnect if we are not connected before hand.
if (pStatus != Connected) {
@ -217,15 +206,12 @@ bool DBcore::Open(
bool iSSL
)
{
LockMutex lock(m_mutex);
safe_delete_array(pHost);
safe_delete_array(pUser);
safe_delete_array(pPassword);
safe_delete_array(pDatabase);
pHost = strcpy(new char[strlen(iHost) + 1], iHost);
pUser = strcpy(new char[strlen(iUser) + 1], iUser);
pPassword = strcpy(new char[strlen(iPassword) + 1], iPassword);
pDatabase = strcpy(new char[strlen(iDatabase) + 1], iDatabase);
std::scoped_lock lock(*m_mutex);
m_host = iHost;
m_user = iUser;
m_password = iPassword;
m_database = iDatabase;
pCompress = iCompress;
pPort = iPort;
pSSL = iSSL;
@ -237,7 +223,9 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
if (errbuf) {
errbuf[0] = 0;
}
LockMutex lock(m_mutex);
std::scoped_lock lock(*m_mutex);
if (GetStatus() == Connected) {
return true;
}
@ -245,7 +233,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
mysql_close(mysql);
mysql_init(mysql); // Initialize structure again
}
if (!pHost) {
if (m_host.empty()) {
return false;
}
/*
@ -268,11 +256,10 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &off);
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &off);
}
if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
if (mysql_real_connect(mysql, m_host.c_str(), m_user.c_str(), m_password.c_str(), m_database.c_str(), pPort, nullptr, flags)) {
pStatus = Connected;
std::string connected_origin_host = pHost;
SetOriginHost(connected_origin_host);
SetOriginHost(m_host);
return true;
}
@ -293,9 +280,9 @@ const std::string &DBcore::GetOriginHost() const
return origin_host;
}
void DBcore::SetOriginHost(const std::string &origin_host)
void DBcore::SetOriginHost(const std::string& originHost)
{
DBcore::origin_host = origin_host;
DBcore::origin_host = originHost;
}
std::string DBcore::Escape(const std::string& s)
@ -307,12 +294,8 @@ std::string DBcore::Escape(const std::string& s)
return temp.data();
}
void DBcore::SetMutex(Mutex *mutex)
void DBcore::SetMutex(const std::shared_ptr<std::mutex>& mutex)
{
if (m_mutex && m_mutex != mutex) {
safe_delete(m_mutex);
}
DBcore::m_mutex = mutex;
}
@ -326,7 +309,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
BenchTimer timer;
timer.reset();
LockMutex lock(m_mutex);
std::scoped_lock lock(*m_mutex);
// Reconnect if we are not connected before hand.
if (pStatus != Connected) {
@ -449,5 +432,5 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
mysql::PreparedStmt DBcore::Prepare(std::string query)
{
return mysql::PreparedStmt(*mysql, std::move(query), m_mutex);
return mysql::PreparedStmt(*mysql, std::move(query), *m_mutex);
}

View File

@ -17,7 +17,6 @@
*/
#pragma once
#include "common/mutex.h"
#include "common/mysql_request_result.h"
#include "common/types.h"
@ -29,7 +28,8 @@
namespace mysql { class PreparedStmt; }
class DBcore {
class DBcore
{
public:
enum eStatus {
Closed, Connected, Error
@ -48,17 +48,17 @@ public:
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
void ping();
const std::string &GetOriginHost() const;
void SetOriginHost(const std::string &origin_host);
const std::string& GetOriginHost() const;
void SetOriginHost(const std::string& origin_host);
bool DoesTableExist(const std::string& table_name);
void SetMySQL(const DBcore &o)
void SetMySQL(const DBcore& o)
{
mysql = o.mysql;
mysqlOwner = false;
}
void SetMutex(Mutex *mutex);
void SetMutex(const std::shared_ptr<std::mutex>& mutex);
// only safe on connections shared with other threads if results buffered
// unsafe to use off main thread due to internal server logging
@ -81,22 +81,22 @@ protected:
private:
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
MYSQL* mysql;
bool mysqlOwner;
Mutex *m_mutex;
eStatus pStatus;
MYSQL* mysql = nullptr;
bool mysqlOwner = true;
eStatus pStatus = Closed;
std::mutex m_query_lock{};
std::shared_ptr<std::mutex> m_mutex;
std::mutex m_query_lock;
std::string origin_host;
char *pHost;
char *pUser;
char *pPassword;
char *pDatabase;
bool pCompress;
uint32 pPort;
bool pSSL;
std::string m_host;
std::string m_user;
std::string m_password;
std::string m_database;
bool pCompress = false;
uint32 pPort = 0;
bool pSSL = false;
// allows multiple queries to be executed within the same query
// do not use this under normal operation

View File

@ -1,162 +0,0 @@
/* EQEmu: EQEmulator
Copyright (C) 2001-2026 EQEmu Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mutex.h"
#include <iostream>
#define DEBUG_MUTEX_CLASS 0
#if DEBUG_MUTEX_CLASS >= 1
#endif
#ifdef _WINDOWS
bool IsTryLockSupported();
bool TrylockSupported = IsTryLockSupported();
bool IsTryLockSupported() {
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) {
#if DEBUG_MUTEX_CLASS >= 1
std::cout << "Mutex::trylock() NOT supported" << std::endl;
#endif
return false;
}
}
// Tests for Windows NT product family.
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 4) {
#if DEBUG_MUTEX_CLASS >= 1
std::cout << "Mutex::trylock() SUPPORTED" << std::endl;
#endif
return true;
}
else {
#if DEBUG_MUTEX_CLASS >= 1
std::cout << "Mutex::trylock() NOT supported" << std::endl;
#endif
return false;
}
}
#endif
Mutex::Mutex() {
#if DEBUG_MUTEX_CLASS >= 7
std::cout << "Constructing Mutex" << std::endl;
#endif
#ifdef _WINDOWS
InitializeCriticalSection(&CSMutex);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if defined(__CYGWIN__) || defined(__APPLE__) || defined(FREEBSD)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#else
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
#endif
pthread_mutex_init(&CSMutex, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
Mutex::~Mutex() {
#ifdef _WINDOWS
DeleteCriticalSection(&CSMutex);
#else
#endif
}
void Mutex::lock() {
#if DEBUG_MUTEX_CLASS >= 5
if (!trylock()) {
std::cout << "Locking Mutex: Having to wait" << std::endl;
#ifdef _WINDOWS
EnterCriticalSection(&CSMutex);
#else
pthread_mutex_lock(&CSMutex);
#endif
}
#else
#ifdef _WINDOWS
EnterCriticalSection(&CSMutex);
#else
pthread_mutex_lock(&CSMutex);
#endif
#endif
}
bool Mutex::trylock() {
#ifdef _WINDOWS
#if(_WIN32_WINNT >= 0x0400)
if (TrylockSupported)
return TryEnterCriticalSection(&CSMutex);
else {
EnterCriticalSection(&CSMutex);
return true;
}
#else
EnterCriticalSection(&CSMutex);
return true;
#endif
#else
return (pthread_mutex_trylock(&CSMutex) == 0);
#endif
}
void Mutex::unlock() {
#ifdef _WINDOWS
LeaveCriticalSection(&CSMutex);
#else
pthread_mutex_unlock(&CSMutex);
#endif
}
LockMutex::LockMutex(Mutex* in_mut, bool iLock) {
mut = in_mut;
locked = iLock;
if (locked) {
mut->lock();
}
}
LockMutex::~LockMutex() {
if (locked) {
mut->unlock();
}
}
void LockMutex::unlock() {
if (locked)
mut->unlock();
locked = false;
}
void LockMutex::lock() {
if (!locked)
mut->lock();
locked = true;
}

View File

@ -1,50 +0,0 @@
/* EQEmu: EQEmulator
Copyright (C) 2001-2026 EQEmu Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/types.h"
#include "common/platform/posix/include_pthreads.h"
#include "common/platform/win/include_windows.h"
class Mutex {
public:
Mutex();
~Mutex();
void lock();
void unlock();
bool trylock();
protected:
private:
#if defined _WINDOWS
CRITICAL_SECTION CSMutex;
#else
pthread_mutex_t CSMutex;
#endif
};
class LockMutex {
public:
LockMutex(Mutex* in_mut, bool iLock = true);
~LockMutex();
void unlock();
void lock();
private:
bool locked;
Mutex* mut;
};

View File

@ -18,7 +18,6 @@
#include "mysql_stmt.h"
#include "common/eqemu_logsys.h"
#include "common/mutex.h"
#include "common/timer.h"
#include <charconv>
@ -31,14 +30,19 @@ void PreparedStmt::StmtDeleter::operator()(MYSQL_STMT* stmt) noexcept
// The connection must be locked when closing the stmt to avoid mysql errors
// in case another thread tries to use it during the close. If the mutex is
// changed to one that throws then exceptions need to be caught here.
LockMutex lock(mutex);
std::scoped_lock lock(mutex);
mysql_stmt_close(stmt);
}
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts)
: m_stmt(mysql_stmt_init(&mysql), { mutex }), m_query(std::move(query)), m_mutex(mutex), m_options(opts)
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, std::mutex& mutex, StmtOptions opts)
: m_stmt(mysql_stmt_init(&mysql), { mutex })
, m_query(std::move(query))
, m_options(opts)
, m_mutex(mutex)
{
LockMutex lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (mysql_stmt_prepare(m_stmt.get(), m_query.c_str(), static_cast<unsigned long>(m_query.size())) != 0)
{
ThrowError(fmt::format("Prepare error: {}", GetStmtError()));
@ -186,7 +190,7 @@ void PreparedStmt::CheckArgs(size_t argc)
StmtResult PreparedStmt::DoExecute()
{
BenchTimer timer;
LockMutex lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_need_bind && mysql_stmt_bind_param(m_stmt.get(), m_params.data()) != 0)
{

View File

@ -17,10 +17,12 @@
*/
#pragma once
#include "mysql.h"
#include <cassert>
#include <cstring>
#include <memory>
#include <mutex>
#include <optional>
#include <span>
#include <string_view>
@ -183,7 +185,7 @@ public:
int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>;
PreparedStmt() = delete;
PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts = {});
PreparedStmt(MYSQL& mysql, std::string query, std::mutex& mutex, StmtOptions opts = {});
const std::string& GetQuery() const { return m_query; }
StmtOptions GetOptions() const { return m_options; }
@ -219,7 +221,8 @@ private:
struct StmtDeleter
{
Mutex* mutex = nullptr;
std::mutex& mutex;
void operator()(MYSQL_STMT* stmt) noexcept;
};
@ -232,7 +235,7 @@ private:
std::string m_query;
StmtOptions m_options = {};
bool m_need_bind = true;
Mutex* m_mutex = nullptr; // connection mutex
std::mutex& m_mutex; // connection mutex
};
} // namespace mysql

View File

@ -142,10 +142,12 @@ RegularOpcodeManager::~RegularOpcodeManager() {
safe_delete_array(eq_to_emu);
}
bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) {
bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors)
{
std::scoped_lock lock(MOpcodes);
NormalMemStrategy s;
s.it = this;
MOpcodes.lock();
loaded = true;
eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
@ -158,32 +160,30 @@ bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors)
memset(emu_to_eq, 0, sizeof(uint16)*_maxEmuOpcode);
bool ret = LoadOpcodesFile(filename, &s, report_errors);
MOpcodes.unlock();
return ret;
}
bool RegularOpcodeManager::ReloadOpcodes(const char *filename, bool report_errors) {
if(!loaded)
return(LoadOpcodes(filename));
bool RegularOpcodeManager::ReloadOpcodes(const char* filename, bool report_errors)
{
if (!loaded)
return LoadOpcodes(filename);
std::scoped_lock lock(MOpcodes);
NormalMemStrategy s;
s.it = this;
MOpcodes.lock();
memset(eq_to_emu, 0, sizeof(uint16)*MAX_EQ_OPCODE);
bool ret = LoadOpcodesFile(filename, &s, report_errors);
MOpcodes.unlock();
return(ret);
memset(eq_to_emu, 0, sizeof(uint16) * MAX_EQ_OPCODE);
return LoadOpcodesFile(filename, &s, report_errors);
}
uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
//opcode is checked for validity in GetEQOpcode
uint16 res;
MOpcodes.lock();
res = emu_to_eq[emu_op];
MOpcodes.unlock();
{
std::scoped_lock lock(MOpcodes);
res = emu_to_eq[emu_op];
}
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
@ -193,15 +193,18 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
return(res);
}
EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op)
{
//opcode is checked for validity in GetEmuOpcode
//Disabled since current live EQ uses the entire uint16 bitspace for opcodes
// if(eq_op > MAX_EQ_OPCODE)
// return(OP_Unknown);
//Disabled since current live EQ uses the entire uint16 bitspace for opcodes
// if(eq_op > MAX_EQ_OPCODE)
// return(OP_Unknown);
EmuOpcode res;
MOpcodes.lock();
res = eq_to_emu[eq_op];
MOpcodes.unlock();
{
std::scoped_lock lock(MOpcodes);
res = eq_to_emu[eq_op];
}
#ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
#endif

View File

@ -18,10 +18,10 @@
#pragma once
#include "common/emu_opcodes.h"
#include "common/mutex.h"
#include "common/types.h"
#include <map>
#include <mutex>
//enable the use of shared mem opcodes for world and zone only
#ifdef ZONE
@ -56,7 +56,7 @@ public:
protected:
bool loaded; //true if all opcodes loaded
Mutex MOpcodes; //this only protects the local machine
std::mutex MOpcodes; //this only protects the local machine
//in a shared manager, this dosent protect others
static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors);

View File

@ -20,9 +20,12 @@
#include "common/eqemu_config.h"
#include "common/repositories/zone_repository.h"
#include <chrono>
#include <csignal>
#include <thread>
using namespace std::chrono_literals;
Database db;
Database db2;
@ -60,8 +63,6 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser
LogInfo("Database test");
auto mutex = new Mutex;
auto c = EQEmuConfig::get();
LogInfo("Connecting to MySQL");
if (!db.Connect(
@ -75,19 +76,19 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser
return;
}
db.SetMutex(mutex);
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
db.SetMutex(sharedMutex);
db2.SetMySQL(db);
db2.SetMutex(mutex);
db2.SetMutex(sharedMutex);
std::thread(DatabaseTest).detach();
std::thread(DatabaseTest).detach();
std::thread(DatabaseTestSecondConnection).detach();
while (!stop) {
std::this_thread::sleep_for(0s);
}
safe_delete(mutex);
}

View File

@ -20,7 +20,6 @@
#include "common/eq_packet_structs.h"
#include "common/event/timer.h"
#include "common/linked_list.h"
#include "common/mutex.h"
#include "common/net/servertalk_client_connection.h"
#include "common/net/servertalk_legacy_client_connection.h"
#include "common/queue.h"

View File

@ -18,7 +18,6 @@
#pragma once
#include "common/eq_packet_structs.h"
#include "common/mutex.h"
#include "common/queue.h"
#include "common/servertalk.h"
#include "common/timer.h"

View File

@ -49,8 +49,6 @@
extern WorldConfig Config;
auto mutex = new Mutex;
void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message)
{
// we don't want to loop up with chat messages
@ -180,11 +178,13 @@ bool WorldBoot::LoadDatabaseConnections()
}
else {
content_db.SetMySQL(database);
// when database and content_db share the same underlying mysql connection
// it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads
database.SetMutex(mutex);
content_db.SetMutex(mutex);
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
}
return true;
@ -634,7 +634,6 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
void WorldBoot::Shutdown()
{
safe_delete(mutex);
}
void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message)

View File

@ -26,7 +26,6 @@
#include "common/guilds.h"
#include "common/memory_mapped_file.h"
#include "common/misc.h"
#include "common/mutex.h"
#include "common/net/eqstream.h"
#include "common/opcodemgr.h"
#include "common/patches/patches.h"
@ -216,8 +215,6 @@ int main(int argc, char **argv)
}
}
auto mutex = new Mutex;
LogInfo("Connecting to MySQL");
if (!database.Connect(
Config->DatabaseHost.c_str(),
@ -245,11 +242,13 @@ int main(int argc, char **argv)
}
} else {
content_db.SetMySQL(database);
// when database and content_db share the same underlying mysql connection
// it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads
database.SetMutex(mutex);
content_db.SetMutex(mutex);
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
}
//rules:
@ -661,7 +660,6 @@ int main(int argc, char **argv)
LogInfo("Proper zone shutdown complete.");
EQEmuLogSys::Instance()->CloseFileLogs();
safe_delete(mutex);
safe_delete(QServ);
return 0;

View File

@ -135,10 +135,11 @@ void PetitionList::AddPetition(Petition* pet) {
}
//Return Values: 0 = Ok ; -1 = Error deleting petition.
int PetitionList::DeletePetition(uint32 petnumber) {
int PetitionList::DeletePetition(uint32 petnumber)
{
LinkedListIterator<Petition*> iterator(list);
iterator.Reset();
LockMutex lock(&PList_Mutex);
std::scoped_lock lock(PList_Mutex);
while(iterator.MoreElements()) {
if (iterator.GetData()->GetID() == petnumber) {
database.DeletePetitionFromDB(iterator.GetData());
@ -179,18 +180,18 @@ void PetitionList::ClearPetitions() {
return;
}
void PetitionList::ReadDatabase() {
LockMutex lock(&PList_Mutex);
void PetitionList::ReadDatabase()
{
std::scoped_lock lock(PList_Mutex);
ClearPetitions();
database.RefreshPetitionsFromDB();
UpdateGMQueue();
return;
}
void PetitionList::UpdatePetition(Petition* pet) {
LockMutex lock(&PList_Mutex);
void PetitionList::UpdatePetition(Petition* pet)
{
std::scoped_lock lock(PList_Mutex);
database.UpdatePetitionToDB(pet);
return;
}
void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) {

View File

@ -18,12 +18,9 @@
#pragma once
#include "common/linked_list.h"
#include "common/misc_functions.h"
#include "common/mutex.h"
#include "common/types.h"
#include "common/zone_store.h"
#include "zone/client.h"
#include "zone/zonedb.h"
#include <mutex>
class Client;
@ -118,5 +115,5 @@ public:
private:
LinkedList<Petition*> list;
Mutex PList_Mutex;
std::mutex PList_Mutex;
};