mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-27 12:22:27 +00:00
Remove Mutex class, replace with std::mutex
Also removes unused Condition class
This commit is contained in:
parent
4693b11cb2
commit
e12c52a66a
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
};
|
||||
@ -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;
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
162
common/mutex.cpp
162
common/mutex.cpp
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user