From 86678d4f7a447cbdd8aa343f8819e541ca72b3ee Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 6 Sep 2015 13:23:20 +0200 Subject: [PATCH] Fix for #621 --- src/object/object_manager.cpp | 19 ++++++++++--- src/object/object_manager.h | 52 ++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/object/object_manager.cpp b/src/object/object_manager.cpp index 079c2f65..a1addd2d 100644 --- a/src/object/object_manager.cpp +++ b/src/object/object_manager.cpp @@ -45,9 +45,14 @@ CObjectManager::CObjectManager(Gfx::CEngine* engine, Gfx::COldModelManager* oldModelManager, Gfx::CModelManager* modelManager, Gfx::CParticle* particle) - : m_objectFactory(MakeUnique(engine, terrain, oldModelManager, modelManager, particle)) - , m_nextId(0) - , m_shouldCleanRemovedObjects(false) + : m_objectFactory(MakeUnique(engine, + terrain, + oldModelManager, + modelManager, + particle)), + m_nextId(0), + m_activeObjectIterators(0), + m_shouldCleanRemovedObjects(false) { } @@ -75,8 +80,14 @@ bool CObjectManager::DeleteObject(CObject* instance) return false; } -void CObjectManager::CleanRemovedObjects() +void CObjectManager::CleanRemovedObjectsIfNeeded() { + if (m_activeObjectIterators != 0) + return; + + if (! m_shouldCleanRemovedObjects) + return; + auto it = m_objects.begin(); if (it != m_objects.end()) { diff --git a/src/object/object_manager.h b/src/object/object_manager.h index 82570f2f..5456ef92 100644 --- a/src/object/object_manager.h +++ b/src/object/object_manager.h @@ -66,13 +66,21 @@ using CObjectMapCIt = std::map>::const_iterator; class CObjectIteratorProxy { +private: + friend class CObjectContainerProxy; + + CObjectIteratorProxy(CObjectMapCIt currentIt, CObjectMapCIt endIt) + : m_currentIt(currentIt) + , m_endIt(endIt) + {} + public: - inline CObject* operator*() + CObject* operator*() { return m_currentIt->second.get(); } - inline void operator++() + void operator++() { do { @@ -81,19 +89,11 @@ public: while (m_currentIt != m_endIt && m_currentIt->second == nullptr); } - inline bool operator!=(const CObjectIteratorProxy& other) + bool operator!=(const CObjectIteratorProxy& other) { return m_currentIt != other.m_currentIt; } -private: - friend class CObjectContainerProxy; - - CObjectIteratorProxy(CObjectMapCIt currentIt, CObjectMapCIt endIt) - : m_currentIt(currentIt) - , m_endIt(endIt) - {} - private: CObjectMapCIt m_currentIt; CObjectMapCIt m_endIt; @@ -104,22 +104,31 @@ class CObjectContainerProxy private: friend class CObjectManager; - inline CObjectContainerProxy(const CObjectMap& map) - : m_map(map) - {} + CObjectContainerProxy(const CObjectMap& map, int& activeIteratorsCounter) + : m_map(map), + m_activeIteratorsCounter(activeIteratorsCounter) + { + ++m_activeIteratorsCounter; + } public: - inline CObjectIteratorProxy begin() const + ~CObjectContainerProxy() + { + --m_activeIteratorsCounter; + } + + CObjectIteratorProxy begin() const { return CObjectIteratorProxy(m_map.begin(), m_map.end()); } - inline CObjectIteratorProxy end() const + CObjectIteratorProxy end() const { return CObjectIteratorProxy(m_map.end(), m_map.end()); } private: const CObjectMap& m_map; + int& m_activeIteratorsCounter; }; /** @@ -167,12 +176,10 @@ public: int CountObjectsImplementing(ObjectInterfaceType interface); //! Returns all objects - inline CObjectContainerProxy GetAllObjects() + CObjectContainerProxy GetAllObjects() { - if (m_shouldCleanRemovedObjects) - CleanRemovedObjects(); - - return CObjectContainerProxy(m_objects); + CleanRemovedObjectsIfNeeded(); + return CObjectContainerProxy(m_objects, m_activeObjectIterators); } //! Finds an object, like radar() in CBot @@ -241,11 +248,12 @@ public: //@} private: - void CleanRemovedObjects(); + void CleanRemovedObjectsIfNeeded(); private: CObjectMap m_objects; std::unique_ptr m_objectFactory; int m_nextId; + int m_activeObjectIterators; bool m_shouldCleanRemovedObjects; };