mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-22 21:26:23 +00:00
feat(Core/Threading): replace ace threading (#4821)
This commit is contained in:
@@ -80,7 +80,7 @@ namespace MMAP
|
||||
return uint32(x << 16 | y);
|
||||
}
|
||||
|
||||
ACE_RW_Thread_Mutex& MMapManager::GetMMapLock(uint32 mapId)
|
||||
std::shared_mutex& MMapManager::GetMMapLock(uint32 mapId)
|
||||
{
|
||||
Map* map = sMapMgr->FindBaseMap(mapId);
|
||||
if (!map)
|
||||
@@ -88,12 +88,13 @@ namespace MMAP
|
||||
sLog->outMisc("ZOMG! MoveMaps: BaseMap not found!");
|
||||
return this->MMapLock;
|
||||
}
|
||||
|
||||
return map->GetMMapLock();
|
||||
}
|
||||
|
||||
bool MMapManager::loadMap(uint32 mapId, int32 x, int32 y)
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
std::unique_lock<std::shared_mutex> guard(MMapManagerLock);
|
||||
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
if (!loadMapData(mapId))
|
||||
@@ -161,7 +162,7 @@ namespace MMAP
|
||||
|
||||
dtStatus stat;
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
||||
std::unique_lock<std::shared_mutex> guard(GetMMapLock(mapId));
|
||||
stat = mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef);
|
||||
}
|
||||
|
||||
@@ -188,7 +189,7 @@ namespace MMAP
|
||||
|
||||
bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
std::unique_lock<std::shared_mutex> guard(MMapManagerLock);
|
||||
|
||||
// check if we have this map loaded
|
||||
if (loadedMMaps.find(mapId) == loadedMMaps.end())
|
||||
@@ -217,7 +218,7 @@ namespace MMAP
|
||||
|
||||
dtStatus status;
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
||||
std::unique_lock<std::shared_mutex> guard(GetMMapLock(mapId));
|
||||
status = mmap->navMesh->removeTile(tileRef, nullptr, nullptr);
|
||||
}
|
||||
|
||||
@@ -245,7 +246,7 @@ namespace MMAP
|
||||
|
||||
bool MMapManager::unloadMap(uint32 mapId)
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
std::unique_lock<std::shared_mutex> guard(MMapManagerLock);
|
||||
|
||||
if (loadedMMaps.find(mapId) == loadedMMaps.end())
|
||||
{
|
||||
@@ -265,7 +266,7 @@ namespace MMAP
|
||||
|
||||
dtStatus status;
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
||||
std::unique_lock<std::shared_mutex> guard(GetMMapLock(mapId));
|
||||
status = mmap->navMesh->removeTile(i->second, nullptr, nullptr);
|
||||
}
|
||||
|
||||
@@ -291,7 +292,7 @@ namespace MMAP
|
||||
|
||||
bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
std::unique_lock<std::shared_mutex> guard(MMapManagerLock);
|
||||
|
||||
// check if we have this map loaded
|
||||
if (loadedMMaps.find(mapId) == loadedMMaps.end())
|
||||
@@ -325,9 +326,6 @@ namespace MMAP
|
||||
|
||||
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
|
||||
{
|
||||
// pussywizard: moved to calling function
|
||||
//ACORE_READ_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
|
||||
if (loadedMMaps.find(mapId) == loadedMMaps.end())
|
||||
return nullptr;
|
||||
|
||||
@@ -336,9 +334,6 @@ namespace MMAP
|
||||
|
||||
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
// pussywizard: moved to calling function
|
||||
//ACORE_READ_GUARD(ACE_RW_Thread_Mutex, MMapManagerLock);
|
||||
|
||||
if (loadedMMaps.find(mapId) == loadedMMaps.end())
|
||||
return nullptr;
|
||||
|
||||
@@ -346,7 +341,7 @@ namespace MMAP
|
||||
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
||||
{
|
||||
// pussywizard: different instances of the same map shouldn't access this simultaneously
|
||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
||||
std::unique_lock<std::shared_mutex> guard(GetMMapLock(mapId));
|
||||
// check again after acquiring mutex
|
||||
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "DetourExtended.h"
|
||||
#include "World.h"
|
||||
#include <unordered_map>
|
||||
#include <shared_mutex>
|
||||
|
||||
// memory management
|
||||
inline void* dtCustomAlloc(size_t size, dtAllocHint /*hint*/)
|
||||
@@ -72,9 +73,9 @@ namespace MMAP
|
||||
uint32 getLoadedTilesCount() const { return loadedTiles; }
|
||||
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
|
||||
|
||||
ACE_RW_Thread_Mutex& GetMMapLock(uint32 mapId);
|
||||
ACE_RW_Thread_Mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||
ACE_RW_Thread_Mutex& GetManagerLock() { return MMapManagerLock; }
|
||||
std::shared_mutex& GetMMapLock(uint32 mapId);
|
||||
std::shared_mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||
std::shared_mutex& GetManagerLock() { return MMapManagerLock; }
|
||||
private:
|
||||
bool loadMapData(uint32 mapId);
|
||||
uint32 packTileID(int32 x, int32 y);
|
||||
@@ -82,9 +83,9 @@ namespace MMAP
|
||||
MMapDataSet loadedMMaps;
|
||||
uint32 loadedTiles;
|
||||
|
||||
ACE_RW_Thread_Mutex MMapManagerLock;
|
||||
ACE_RW_Thread_Mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||
std::shared_mutex MMapManagerLock;
|
||||
std::shared_mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace VMAP
|
||||
WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
|
||||
{
|
||||
//! Critical section, thread safe access to iLoadedModelFiles
|
||||
ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
|
||||
std::lock_guard<std::mutex> guard(LoadedModelFilesLock);
|
||||
|
||||
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
|
||||
if (model == iLoadedModelFiles.end())
|
||||
@@ -287,7 +287,7 @@ namespace VMAP
|
||||
void VMapManager2::releaseModelInstance(const std::string& filename)
|
||||
{
|
||||
//! Critical section, thread safe access to iLoadedModelFiles
|
||||
ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
|
||||
std::lock_guard<std::mutex> guard(LoadedModelFilesLock);
|
||||
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
|
||||
if (model == iLoadedModelFiles.end())
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "IVMapManager.h"
|
||||
#include "Define.h"
|
||||
#include <ace/Thread_Mutex.h>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
//===========================================================
|
||||
@@ -72,7 +72,7 @@ namespace VMAP
|
||||
ModelFileMap iLoadedModelFiles;
|
||||
InstanceTreeMap iInstanceMapTrees;
|
||||
// Mutex for iLoadedModelFiles
|
||||
ACE_Thread_Mutex LoadedModelFilesLock;
|
||||
std::mutex LoadedModelFilesLock;
|
||||
|
||||
bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY);
|
||||
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
|
||||
|
||||
@@ -78,9 +78,6 @@
|
||||
|
||||
#include "Threading/LockedQueue.h"
|
||||
#include "Threading/Threading.h"
|
||||
|
||||
#include <ace/RW_Thread_Mutex.h>
|
||||
#include <ace/Thread_Mutex.h>
|
||||
#include <ace/Stack_Trace.h>
|
||||
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
@@ -124,8 +121,6 @@ inline float finiteAlways(float f) { return isfinite(f) ? f : 0.0f; }
|
||||
|
||||
inline bool myisfinite(float f) { return isfinite(f) && !isnan(f); }
|
||||
|
||||
#define atol(a) strtoul( a, nullptr, 10)
|
||||
|
||||
#define STRINGIZE(a) #a
|
||||
|
||||
#define MAX_NETCLIENT_PACKET_SIZE (32767 - 1) // Client hardcap: int16 with trailing zero space otherwise crash on memory free
|
||||
@@ -187,22 +182,6 @@ typedef std::vector<std::string> StringVector;
|
||||
|
||||
#define MAX_QUERY_LEN 32*1024
|
||||
|
||||
#define ACORE_GUARD(MUTEX, LOCK) \
|
||||
ACE_Guard< MUTEX > ACORE_GUARD_OBJECT (LOCK); \
|
||||
if (ACORE_GUARD_OBJECT.locked() == 0) ASSERT(false);
|
||||
|
||||
//! For proper implementation of multiple-read, single-write pattern, use
|
||||
//! ACE_RW_Mutex as underlying @MUTEX
|
||||
# define ACORE_WRITE_GUARD(MUTEX, LOCK) \
|
||||
ACE_Write_Guard< MUTEX > ACORE_GUARD_OBJECT (LOCK); \
|
||||
if (ACORE_GUARD_OBJECT.locked() == 0) ASSERT(false);
|
||||
|
||||
//! For proper implementation of multiple-read, single-write pattern, use
|
||||
//! ACE_RW_Mutex as underlying @MUTEX
|
||||
# define ACORE_READ_GUARD(MUTEX, LOCK) \
|
||||
ACE_Read_Guard< MUTEX > ACORE_GUARD_OBJECT (LOCK); \
|
||||
if (ACORE_GUARD_OBJECT.locked() == 0) ASSERT(false);
|
||||
|
||||
namespace acore
|
||||
{
|
||||
template<class ArgumentType, class ResultType>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "QueryHolder.h"
|
||||
#include "AdhocStatement.h"
|
||||
#include "StringFormat.h"
|
||||
#include <ace/Thread_Mutex.h>
|
||||
#include <mutex>
|
||||
|
||||
class PingOperation : public SQLOperation
|
||||
{
|
||||
|
||||
@@ -90,13 +90,13 @@ protected:
|
||||
{
|
||||
/// Tries to acquire lock. If lock is acquired by another thread
|
||||
/// the calling parent will just try another connection
|
||||
return m_Mutex.tryacquire() != -1;
|
||||
return m_Mutex.try_lock();
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
/// Called by parent databasepool. Will let other threads access this connection
|
||||
m_Mutex.release();
|
||||
m_Mutex.unlock();
|
||||
}
|
||||
|
||||
MYSQL* GetHandle() { return m_Mysql; }
|
||||
@@ -120,7 +120,7 @@ private:
|
||||
MYSQL* m_Mysql; //! MySQL Handle.
|
||||
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
|
||||
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
|
||||
ACE_Thread_Mutex m_Mutex;
|
||||
std::mutex m_Mutex;
|
||||
|
||||
MySQLConnection(MySQLConnection const& right) = delete;
|
||||
MySQLConnection& operator=(MySQLConnection const& right) = delete;
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
#ifndef QUERYRESULT_H
|
||||
#define QUERYRESULT_H
|
||||
|
||||
#include <ace/Thread_Mutex.h>
|
||||
|
||||
#include "Errors.h"
|
||||
#include "Field.h"
|
||||
#include <mutex>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
||||
@@ -7,137 +7,134 @@
|
||||
#ifndef LOCKEDQUEUE_H
|
||||
#define LOCKEDQUEUE_H
|
||||
|
||||
#include "Debugging/Errors.h"
|
||||
#include <ace/Guard_T.h>
|
||||
#include <ace/Thread_Mutex.h>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
|
||||
namespace ACE_Based
|
||||
template <class T, typename StorageType = std::deque<T> >
|
||||
class LockedQueue
|
||||
{
|
||||
template <class T, class LockType, typename StorageType = std::deque<T>>
|
||||
class LockedQueue
|
||||
//! Lock access to the queue.
|
||||
std::mutex _lock;
|
||||
|
||||
//! Storage backing the queue.
|
||||
StorageType _queue;
|
||||
|
||||
//! Cancellation flag.
|
||||
volatile bool _canceled;
|
||||
|
||||
public:
|
||||
|
||||
//! Create a LockedQueue.
|
||||
LockedQueue()
|
||||
: _canceled(false)
|
||||
{
|
||||
//! Lock access to the queue.
|
||||
LockType _lock;
|
||||
}
|
||||
|
||||
//! Storage backing the queue.
|
||||
StorageType _queue;
|
||||
//! Destroy a LockedQueue.
|
||||
virtual ~LockedQueue()
|
||||
{
|
||||
}
|
||||
|
||||
//! Cancellation flag.
|
||||
volatile bool _canceled{false};
|
||||
//! Adds an item to the queue.
|
||||
void add(const T& item)
|
||||
{
|
||||
lock();
|
||||
|
||||
public:
|
||||
//! Create a LockedQueue.
|
||||
LockedQueue()
|
||||
_queue.push_back(item);
|
||||
|
||||
{
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
//! Destroy a LockedQueue.
|
||||
virtual ~LockedQueue() = default;
|
||||
//! Adds items back to front of the queue
|
||||
template<class Iterator>
|
||||
void readd(Iterator begin, Iterator end)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.insert(_queue.begin(), begin, end);
|
||||
}
|
||||
|
||||
//! Adds an item to the queue.
|
||||
void add(const T& item)
|
||||
{
|
||||
lock();
|
||||
//! Gets the next result in the queue, if any.
|
||||
bool next(T& result)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
//ASSERT(!this->_canceled);
|
||||
// throw Cancellation_Exception();
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
|
||||
_queue.push_back(item);
|
||||
result = _queue.front();
|
||||
_queue.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Checker>
|
||||
bool next(T& result, Checker& check)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
|
||||
result = _queue.front();
|
||||
if (!check.Process(result))
|
||||
return false;
|
||||
|
||||
_queue.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
|
||||
T& peek(bool autoUnlock = false)
|
||||
{
|
||||
lock();
|
||||
|
||||
T& result = _queue.front();
|
||||
|
||||
if (autoUnlock)
|
||||
unlock();
|
||||
}
|
||||
|
||||
//! Gets the next result in the queue, if any.
|
||||
bool next(T& result)
|
||||
{
|
||||
// ACE_Guard<LockType> g(this->_lock);
|
||||
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
//! Cancels the queue.
|
||||
void cancel()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
//ASSERT (!_queue.empty() || !this->_canceled);
|
||||
// throw Cancellation_Exception();
|
||||
result = _queue.front();
|
||||
_queue.pop_front();
|
||||
_canceled = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//! Checks if the queue is cancelled.
|
||||
bool cancelled()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _canceled;
|
||||
}
|
||||
|
||||
template<class Checker>
|
||||
bool next(T& result, Checker& check)
|
||||
{
|
||||
ACE_Guard<LockType> g(this->_lock);
|
||||
//! Locks the queue for access.
|
||||
void lock()
|
||||
{
|
||||
this->_lock.lock();
|
||||
}
|
||||
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
//! Unlocks the queue.
|
||||
void unlock()
|
||||
{
|
||||
this->_lock.unlock();
|
||||
}
|
||||
|
||||
result = _queue.front();
|
||||
if (!check.Process(result))
|
||||
return false;
|
||||
///! Calls pop_front of the queue
|
||||
void pop_front()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.pop_front();
|
||||
}
|
||||
|
||||
_queue.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
|
||||
T& peek(bool autoUnlock = false)
|
||||
{
|
||||
lock();
|
||||
|
||||
T& result = _queue.front();
|
||||
|
||||
if (autoUnlock)
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Cancels the queue.
|
||||
void cancel()
|
||||
{
|
||||
lock();
|
||||
|
||||
_canceled = true;
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
//! Checks if the queue is cancelled.
|
||||
bool cancelled()
|
||||
{
|
||||
ACE_Guard<LockType> g(this->_lock);
|
||||
return _canceled;
|
||||
}
|
||||
|
||||
//! Locks the queue for access.
|
||||
void lock()
|
||||
{
|
||||
this->_lock.acquire();
|
||||
}
|
||||
|
||||
//! Unlocks the queue.
|
||||
void unlock()
|
||||
{
|
||||
this->_lock.release();
|
||||
}
|
||||
|
||||
///! Calls pop_front of the queue
|
||||
void pop_front()
|
||||
{
|
||||
ACE_GUARD (LockType, g, this->_lock);
|
||||
_queue.pop_front();
|
||||
}
|
||||
|
||||
///! Checks if we're empty or not with locks held
|
||||
bool empty()
|
||||
{
|
||||
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
||||
return _queue.empty();
|
||||
}
|
||||
};
|
||||
}
|
||||
///! Checks if we're empty or not with locks held
|
||||
bool empty()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _queue.empty();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user