Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

destroy objects before deleting identifiers (when unloading a module)

File:
1 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}
Note: See TracChangeset for help on using the changeset viewer.