diff --git a/src/framework/Utilities/LinkedList.h b/src/framework/Utilities/LinkedList.h index 7ca217fe7..97fbce4ae 100644 --- a/src/framework/Utilities/LinkedList.h +++ b/src/framework/Utilities/LinkedList.h @@ -44,6 +44,11 @@ class LinkedListElement LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; } LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; } + LinkedListElement * nocheck_next() { return iNext; } + LinkedListElement const* nocheck_next() const { return iNext; } + LinkedListElement * nocheck_prev() { return iPrev; } + LinkedListElement const* nocheck_prev() const { return iPrev; } + void delink() { if(isInList()) @@ -134,7 +139,10 @@ class LinkedListHead typedef ptrdiff_t difference_type; typedef ptrdiff_t distance_type; typedef _Ty* pointer; + typedef _Ty const* const_pointer; typedef _Ty& reference; + typedef _Ty const & const_reference; + Iterator() : _Ptr(0) { // construct with null node pointer @@ -144,6 +152,17 @@ class LinkedListHead { // construct with node pointer _Pnode } + Iterator& operator=(Iterator const &_Right) + { + return (*this) = _Right._Ptr; + } + + Iterator& operator=(const_pointer const &_Right) + { + _Ptr = (pointer)_Right; + return (*this); + } + reference operator*() { // return designated value return *_Ptr; @@ -200,6 +219,17 @@ class LinkedListHead return (!(*this == _Right)); } + bool operator==(const_reference _Right) const + { // test for reference equality + return (_Ptr == &_Right); + } + + bool operator!=(const_reference _Right) const + { // test for reference equality + return (_Ptr != &_Right)); + } + + pointer _Mynode() { // return node pointer return (_Ptr); diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h index a3c879709..3c84704dc 100644 --- a/src/framework/Utilities/LinkedReference/Reference.h +++ b/src/framework/Utilities/LinkedReference/Reference.h @@ -71,9 +71,15 @@ template class Reference : public LinkedListElement return iRefTo != NULL; } - Reference* next() { return((Reference*)LinkedListElement::next()); } - Referenceconst* next() const { return((Reference const*)LinkedListElement::next()); } - Reference* prev() { return((Reference*)LinkedListElement::prev()); } + Reference * next() { return((Reference *) LinkedListElement::next()); } + Reference const * next() const { return((Reference const *) LinkedListElement::next()); } + Reference * prev() { return((Reference *) LinkedListElement::prev()); } + Reference const * prev() const { return((Reference const *) LinkedListElement::prev()); } + + Reference * nocheck_next() { return((Reference *) LinkedListElement::nocheck_next()); } + Reference const * nocheck_next() const { return((Reference const *) LinkedListElement::nocheck_next()); } + Reference * nocheck_prev() { return((Reference *) LinkedListElement::nocheck_prev()); } + Reference const * nocheck_prev() const { return((Reference const *) LinkedListElement::nocheck_prev()); } inline TO* operator ->() const { return iRefTo; } inline TO* getTarget() const { return iRefTo; } diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 4da16004b..d782f6cba 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -573,21 +573,15 @@ void Map::Update(const uint32 &t_diff) // for pets TypeContainerVisitor world_object_update(updater); - //TODO: Player guard - HashMapHolder::MapType& playerMap = HashMapHolder::GetContainer(); - for(HashMapHolder::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter) + // the player iterator is stored in the map object + // to make sure calls to Map::Remove don't invalidate it + for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) { - Player* plr = iter->second; + Player* plr = m_mapRefIter->getSource(); if(!plr->IsInWorld()) continue; - if(plr->GetMapId() != GetId()) - continue; - - if(plr->GetInstanceId() != GetInstanceId()) - continue; - CellPair standing_cell(MaNGOS::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY())); // Check for correctness of standing_cell, it also avoids problems with update_cell @@ -640,6 +634,13 @@ void Map::Update(const uint32 &t_diff) void Map::Remove(Player *player, bool remove) { + // this may be called during Map::Update + // after decrement+unlink, ++m_mapRefIter will continue correctly + // when the first element of the list is being removed + // nocheck_prev will return the padding element of the RefManager + // instead of NULL in the case of prev + if(m_mapRefIter == player->GetMapRef()) + m_mapRefIter = m_mapRefIter->nocheck_prev(); player->GetMapRef().unlink(); CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) diff --git a/src/game/Map.h b/src/game/Map.h index d24523e84..1fe978754 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -292,6 +292,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj uint32 m_unloadTimer; MapRefManager m_mapRefManager; + MapRefManager::iterator m_mapRefIter; private: typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; diff --git a/src/game/MapReference.h b/src/game/MapReference.h index 4ab1d116d..e58e06cf8 100644 --- a/src/game/MapReference.h +++ b/src/game/MapReference.h @@ -46,5 +46,7 @@ class MANGOS_DLL_SPEC MapReference : public Reference ~MapReference() { unlink(); } MapReference *next() { return (MapReference*)Reference::next(); } MapReference const *next() const { return (MapReference const*)Reference::next(); } + MapReference *nockeck_prev() { return (MapReference*)Reference::nocheck_prev(); } + MapReference const *nocheck_prev() const { return (MapReference const*)Reference::nocheck_prev(); } }; #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2ca2e69e8..4ffc9d5e7 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6854" + #define REVISION_NR "6855" #endif // __REVISION_NR_H__