Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 10539


Ignore:
Timestamp:
Jun 7, 2015, 12:10:24 PM (9 years ago)
Author:
landauf
Message:

destroy objects before deleting identifiers (when unloading a module)

Location:
code/branches/core7/src/libraries/core
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.cc

    r10538 r10539  
    2929#include "CoreStaticInitializationHandler.h"
    3030
     31#include "CoreIncludes.h"
    3132#include "module/ModuleInstance.h"
    3233#include "class/IdentifierManager.h"
     34#include "object/Iterator.h"
    3335
    3436namespace orxonox
     
    5355    void CoreStaticInitializationHandler::loadInstances(ModuleInstance* module)
    5456    {
    55         // the order of initialization is important
     57        // the order of initialization is important: handlers > identifiers > singletons > everything else
    5658        module->loadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
    5759        module->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
     
    7274        module->unloadAllStaticallyInitializedInstances(StaticInitialization::COMMAND_LINE_ARGUMENT);
    7375        module->unloadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
     76
     77        // until now every object (including singletons) of the unloaded identifiers should have been destroyed in a controlled manner.
     78        // every remaining object is now destroyed in random order.
     79        this->destroyObjects(module);
     80
     81        // all objects are gone now and we can unload identifiers
    7482        module->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
    7583        module->unloadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
    7684    }
     85
     86    void CoreStaticInitializationHandler::destroyObjects(ModuleInstance* module)
     87    {
     88        // collect all identifiers that are about to be unloaded
     89        std::set<Identifier*> identifiers;
     90        const std::set<StaticallyInitializedInstance*>& instances = module->getInstances(StaticInitialization::IDENTIFIER);
     91        for (std::set<StaticallyInitializedInstance*>::const_iterator it = instances.begin(); it != instances.end(); ++it)
     92            identifiers.insert(&static_cast<StaticallyInitializedIdentifier*>(*it)->getIdentifier());
     93
     94        // destroy objects. some objects may survive this at first because they still have smart pointers pointing at them. this is
     95        // ok as long as those smart pointers are held by objects that are also about to be destroyed in the same loop. this means
     96        // that objects within one module may reference each other by smart pointers. but it is not allowed that objects from another
     97        // module (which is not unloaded) uses smart pointers to point at objects inside the unloaded module. this will lead to a crash.
     98        for (std::set<Identifier*>::iterator it = identifiers.begin(); it != identifiers.end(); ++it)
     99            (*it)->destroyObjects();
     100
     101        // check if all objects were really destroyed. this is not the case if an object is referenced by a smart pointer from another
     102        // module (or if two objects inside this module reference each other). this will lead to a crash and must be fixed (e.g. by
     103        // changing object dependencies; or by changing the logic that allows modules to be unloaded).
     104        for (std::set<Identifier*>::iterator it = identifiers.begin(); it != identifiers.end(); ++it)
     105        {
     106            ObjectListBase* objectList = Context::getRootContext()->getObjectList(*it);
     107            if (objectList->size() > 0)
     108            {
     109                orxout(internal_error) << "There are still " << objectList->size() << " objects of type " << (*it)->getName()
     110                    << " after unloading the Identifier. This may lead to a crash" << endl;
     111            }
     112        }
     113
     114        // destroy object-lists in all contexts
     115        for (std::set<Identifier*>::iterator it_identifier = identifiers.begin(); it_identifier != identifiers.end(); ++it_identifier)
     116        {
     117            // only do this if the Identifier is not a Context itself; otherwise we delete the list we're iterating over
     118            if (!(*it_identifier)->isExactlyA(Class(Context)))
     119            {
     120                // iterate over all contexts
     121                for (ObjectList<Context>::iterator it_context = ObjectList<Context>::begin(); it_context != ObjectList<Context>::end(); ++it_context)
     122                    it_context->destroyObjectList((*it_identifier));
     123            }
     124        }
     125    }
    77126}
  • code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.h

    r10535 r10539  
    5656            void initInstances(ModuleInstance* module);
    5757
     58            void destroyObjects(ModuleInstance* module);
     59
    5860            bool bInitInstances_;
    5961    };
  • code/branches/core7/src/libraries/core/class/Identifier.h

    r10537 r10539  
    152152            inline bool isInitialized() const { return this->bInitialized_; }
    153153
     154            virtual void destroyObjects() = 0;
     155
     156            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
     157
     158            static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
     159
    154160
    155161            /////////////////////////////
     
    215221            XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
    216222
    217             virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
    218 
    219             static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
    220 
    221223        protected:
    222224            virtual void createSuperFunctionCaller() const = 0;
     
    297299                { return dynamic_cast<T*>(object) != 0; }
    298300
     301            virtual void destroyObjects();
     302
    299303            static ClassIdentifier<T>* getIdentifier();
    300304
     
    307311            void addObjectToList(T* object, Listable*);
    308312            void addObjectToList(T* object, Identifiable*);
     313
     314            void destroyObjects(Listable*);
     315            void destroyObjects(void*);
     316
     317            void destroyObject(Destroyable* object);
     318            void destroyObject(void* object);
    309319
    310320            void updateConfigValues(bool updateChildren, Listable*) const;
     
    389399    {
    390400        // no action
     401    }
     402
     403    /**
     404     * @brief Destroy all objects of this class (must be Listable).
     405     * Destroyables are destroyed with destroy(), all other classes with delete.
     406     */
     407    template <class T>
     408    void ClassIdentifier<T>::destroyObjects()
     409    {
     410        this->destroyObjects((T*)0);
     411    }
     412
     413    /**
     414     * @brief Only searches and destroys objects if is a @ref Listable
     415     */
     416    template <class T>
     417    void ClassIdentifier<T>::destroyObjects(Listable*)
     418    {
     419        ObjectListBase* objectList = Context::getRootContext()->getObjectList(this);
     420        ObjectListElement<T>* begin = static_cast<ObjectListElement<T>*>(objectList->begin());
     421        ObjectListElement<T>* end = static_cast<ObjectListElement<T>*>(objectList->end());
     422        for (typename ObjectList<T>::iterator it = begin; it != end; )
     423            this->destroyObject(*(it++));
     424    }
     425
     426    template <class T>
     427    void ClassIdentifier<T>::destroyObjects(void*)
     428    {
     429        // no action
     430    }
     431
     432    /**
     433     * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types.
     434     */
     435    template <class T>
     436    void ClassIdentifier<T>::destroyObject(Destroyable* object)
     437    {
     438        object->destroy();
     439    }
     440
     441    template <class T>
     442    void ClassIdentifier<T>::destroyObject(void* object)
     443    {
     444        delete static_cast<Identifiable*>(object);
    391445    }
    392446
  • code/branches/core7/src/libraries/core/module/ModuleInstance.h

    r10535 r10539  
    5252            void unloadAllStaticallyInitializedInstances(StaticInitialization::Type type);
    5353
     54            inline const std::set<StaticallyInitializedInstance*>& getInstances(StaticInitialization::Type type)
     55                { return this->staticallyInitializedInstancesByType_[type]; }
     56
    5457            void deleteAllStaticallyInitializedInstances();
    5558
  • code/branches/core7/src/libraries/core/object/Context.cc

    r9667 r10539  
    9797        return this->objectLists_[classID];
    9898    }
     99
     100    void Context::destroyObjectList(const Identifier* identifier)
     101    {
     102        ObjectListBase* objectList = this->getObjectList(identifier);
     103        delete objectList;
     104        this->objectLists_[identifier->getClassID()] = NULL;
     105    }
    99106}
  • code/branches/core7/src/libraries/core/object/Context.h

    r9667 r10539  
    7171            }
    7272
     73            void destroyObjectList(const Identifier* identifier);
     74
    7375        private:
    7476            Context* parentContext_;
Note: See TracChangeset for help on using the changeset viewer.