[9997] Some changes in HashMapHolder.

* Use ACE_RW_Thread_Mutex, since there's much more reading than writing.
* Use read lock in Find(), and write lock in Insert() and Remove().
* Correctly lock the hashmap on outside calls.
This commit is contained in:
XTZGZoReX 2010-05-28 15:30:23 +02:00
parent aa62225c68
commit a037a26fde
4 changed files with 36 additions and 27 deletions

View file

@ -153,9 +153,10 @@ bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/)
{ {
bool first = true; bool first = true;
HashMapHolder<Player>::MapType &m = HashMapHolder<Player>::GetContainer(); {
HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); HashMapHolder<Player>::ReadGuard g(HashMapHolder<Player>::GetLock());
for(; itr != m.end(); ++itr) HashMapHolder<Player>::MapType &m = sObjectAccessor.GetPlayers();
for(HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
{ {
AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); AccountTypes itr_sec = itr->second->GetSession()->GetSecurity();
if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) &&
@ -170,6 +171,7 @@ bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/)
SendSysMessage(GetNameLink(itr->second).c_str()); SendSysMessage(GetNameLink(itr->second).c_str());
} }
} }
}
if(first) if(first)
SendSysMessage(LANG_GMS_NOT_LOGGED); SendSysMessage(LANG_GMS_NOT_LOGGED);

View file

@ -92,22 +92,21 @@ ObjectAccessor::FindPlayer(ObjectGuid guid)
Player* Player*
ObjectAccessor::FindPlayerByName(const char *name) ObjectAccessor::FindPlayerByName(const char *name)
{ {
//TODO: Player Guard HashMapHolder<Player>::ReadGuard g(HashMapHolder<Player>::GetLock());
HashMapHolder<Player>::MapType& m = HashMapHolder<Player>::GetContainer(); HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers();
HashMapHolder<Player>::MapType::iterator iter = m.begin(); for(HashMapHolder<Player>::MapType::iterator iter = m.begin(); iter != m.end(); ++iter)
for(; iter != m.end(); ++iter)
if(iter->second->IsInWorld() && ( ::strcmp(name, iter->second->GetName()) == 0 )) if(iter->second->IsInWorld() && ( ::strcmp(name, iter->second->GetName()) == 0 ))
return iter->second; return iter->second;
return NULL; return NULL;
} }
void void
ObjectAccessor::SaveAllPlayers() ObjectAccessor::SaveAllPlayers()
{ {
Guard guard(*HashMapHolder<Player>::GetLock()); HashMapHolder<Player>::ReadGuard g(HashMapHolder<Player>::GetLock());
HashMapHolder<Player>::MapType& m = HashMapHolder<Player>::GetContainer(); HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers();
HashMapHolder<Player>::MapType::iterator itr = m.begin(); for(HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr)
for(; itr != m.end(); ++itr)
itr->second->SaveToDB(); itr->second->SaveToDB();
} }
@ -277,7 +276,7 @@ void ObjectAccessor::RemoveOldCorpses()
/// Define the static member of HashMapHolder /// Define the static member of HashMapHolder
template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap; template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap;
template <class T> ACE_Thread_Mutex HashMapHolder<T>::i_lock; template <class T> ACE_RW_Thread_Mutex HashMapHolder<T>::i_lock;
/// Global definitions for the hashmap storage /// Global definitions for the hashmap storage

View file

@ -22,6 +22,7 @@
#include "Platform/Define.h" #include "Platform/Define.h"
#include "Policies/Singleton.h" #include "Policies/Singleton.h"
#include <ace/Thread_Mutex.h> #include <ace/Thread_Mutex.h>
#include <ace/RW_Thread_Mutex.h>
#include "Utilities/UnorderedMap.h" #include "Utilities/UnorderedMap.h"
#include "Policies/ThreadingModel.h" #include "Policies/ThreadingModel.h"
@ -47,26 +48,33 @@ class HashMapHolder
public: public:
typedef UNORDERED_MAP< uint64, T* > MapType; typedef UNORDERED_MAP< uint64, T* > MapType;
typedef ACE_Thread_Mutex LockType; typedef ACE_RW_Thread_Mutex LockType;
typedef MaNGOS::GeneralLock<LockType > Guard; typedef ACE_Read_Guard<LockType> ReadGuard;
typedef ACE_Write_Guard<LockType> WriteGuard;
static void Insert(T* o) { m_objectMap[o->GetGUID()] = o; } static void Insert(T* o)
{
WriteGuard guard(i_lock);
m_objectMap[o->GetGUID()] = o;
}
static void Remove(T* o) static void Remove(T* o)
{ {
Guard guard(i_lock); WriteGuard guard(i_lock);
m_objectMap.erase(o->GetGUID()); m_objectMap.erase(o->GetGUID());
} }
static T* Find(ObjectGuid guid) static T* Find(ObjectGuid guid)
{ {
ReadGuard guard(i_lock);
typename MapType::iterator itr = m_objectMap.find(guid.GetRawValue()); typename MapType::iterator itr = m_objectMap.find(guid.GetRawValue());
return (itr != m_objectMap.end()) ? itr->second : NULL; return (itr != m_objectMap.end()) ? itr->second : NULL;
} }
static MapType& GetContainer() { return m_objectMap; } static MapType& GetContainer() { return m_objectMap; }
static LockType* GetLock() { return &i_lock; } static LockType& GetLock() { return i_lock; }
private: private:
//Non instanceable only static //Non instanceable only static
@ -78,8 +86,8 @@ class HashMapHolder
class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor, MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex> > class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor, MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex> >
{ {
friend class MaNGOS::OperatorNew<ObjectAccessor>; friend class MaNGOS::OperatorNew<ObjectAccessor>;
ObjectAccessor(); ObjectAccessor();
~ObjectAccessor(); ~ObjectAccessor();
ObjectAccessor(const ObjectAccessor &); ObjectAccessor(const ObjectAccessor &);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9996" #define REVISION_NR "9997"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__