[Orxonox-commit 5879] r10539 - in code/branches/core7/src/libraries/core: . class module object
landauf at orxonox.net
landauf at orxonox.net
Sun Jun 7 12:10:25 CEST 2015
Author: landauf
Date: 2015-06-07 12:10:24 +0200 (Sun, 07 Jun 2015)
New Revision: 10539
Modified:
code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.cc
code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.h
code/branches/core7/src/libraries/core/class/Identifier.h
code/branches/core7/src/libraries/core/module/ModuleInstance.h
code/branches/core7/src/libraries/core/object/Context.cc
code/branches/core7/src/libraries/core/object/Context.h
Log:
destroy objects before deleting identifiers (when unloading a module)
Modified: code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.cc
===================================================================
--- code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.cc 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.cc 2015-06-07 10:10:24 UTC (rev 10539)
@@ -28,8 +28,10 @@
#include "CoreStaticInitializationHandler.h"
+#include "CoreIncludes.h"
#include "module/ModuleInstance.h"
#include "class/IdentifierManager.h"
+#include "object/Iterator.h"
namespace orxonox
{
@@ -52,7 +54,7 @@
void CoreStaticInitializationHandler::loadInstances(ModuleInstance* module)
{
- // the order of initialization is important
+ // the order of initialization is important: handlers > identifiers > singletons > everything else
module->loadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
module->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
module->loadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
@@ -71,7 +73,54 @@
module->unloadAllStaticallyInitializedInstances(StaticInitialization::CONSOLE_COMMAND);
module->unloadAllStaticallyInitializedInstances(StaticInitialization::COMMAND_LINE_ARGUMENT);
module->unloadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
+
+ // until now every object (including singletons) of the unloaded identifiers should have been destroyed in a controlled manner.
+ // every remaining object is now destroyed in random order.
+ this->destroyObjects(module);
+
+ // all objects are gone now and we can unload identifiers
module->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
module->unloadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
}
+
+ void CoreStaticInitializationHandler::destroyObjects(ModuleInstance* module)
+ {
+ // collect all identifiers that are about to be unloaded
+ std::set<Identifier*> identifiers;
+ const std::set<StaticallyInitializedInstance*>& instances = module->getInstances(StaticInitialization::IDENTIFIER);
+ for (std::set<StaticallyInitializedInstance*>::const_iterator it = instances.begin(); it != instances.end(); ++it)
+ identifiers.insert(&static_cast<StaticallyInitializedIdentifier*>(*it)->getIdentifier());
+
+ // destroy objects. some objects may survive this at first because they still have smart pointers pointing at them. this is
+ // ok as long as those smart pointers are held by objects that are also about to be destroyed in the same loop. this means
+ // that objects within one module may reference each other by smart pointers. but it is not allowed that objects from another
+ // module (which is not unloaded) uses smart pointers to point at objects inside the unloaded module. this will lead to a crash.
+ for (std::set<Identifier*>::iterator it = identifiers.begin(); it != identifiers.end(); ++it)
+ (*it)->destroyObjects();
+
+ // check if all objects were really destroyed. this is not the case if an object is referenced by a smart pointer from another
+ // module (or if two objects inside this module reference each other). this will lead to a crash and must be fixed (e.g. by
+ // changing object dependencies; or by changing the logic that allows modules to be unloaded).
+ for (std::set<Identifier*>::iterator it = identifiers.begin(); it != identifiers.end(); ++it)
+ {
+ ObjectListBase* objectList = Context::getRootContext()->getObjectList(*it);
+ if (objectList->size() > 0)
+ {
+ orxout(internal_error) << "There are still " << objectList->size() << " objects of type " << (*it)->getName()
+ << " after unloading the Identifier. This may lead to a crash" << endl;
+ }
+ }
+
+ // destroy object-lists in all contexts
+ for (std::set<Identifier*>::iterator it_identifier = identifiers.begin(); it_identifier != identifiers.end(); ++it_identifier)
+ {
+ // only do this if the Identifier is not a Context itself; otherwise we delete the list we're iterating over
+ if (!(*it_identifier)->isExactlyA(Class(Context)))
+ {
+ // iterate over all contexts
+ for (ObjectList<Context>::iterator it_context = ObjectList<Context>::begin(); it_context != ObjectList<Context>::end(); ++it_context)
+ it_context->destroyObjectList((*it_identifier));
+ }
+ }
+ }
}
Modified: code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.h
===================================================================
--- code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.h 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/CoreStaticInitializationHandler.h 2015-06-07 10:10:24 UTC (rev 10539)
@@ -55,6 +55,8 @@
void loadInstances(ModuleInstance* module);
void initInstances(ModuleInstance* module);
+ void destroyObjects(ModuleInstance* module);
+
bool bInitInstances_;
};
}
Modified: code/branches/core7/src/libraries/core/class/Identifier.h
===================================================================
--- code/branches/core7/src/libraries/core/class/Identifier.h 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/class/Identifier.h 2015-06-07 10:10:24 UTC (rev 10539)
@@ -151,7 +151,13 @@
/// Returns true if the Identifier was completely initialized.
inline bool isInitialized() const { return this->bInitialized_; }
+ virtual void destroyObjects() = 0;
+ virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
+
+ static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
+
+
/////////////////////////////
////// Class Hierarchy //////
/////////////////////////////
@@ -214,10 +220,6 @@
void addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container);
XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
- virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
-
- static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
-
protected:
virtual void createSuperFunctionCaller() const = 0;
@@ -296,6 +298,8 @@
virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const
{ return dynamic_cast<T*>(object) != 0; }
+ virtual void destroyObjects();
+
static ClassIdentifier<T>* getIdentifier();
private:
@@ -307,6 +311,12 @@
void addObjectToList(T* object, Listable*);
void addObjectToList(T* object, Identifiable*);
+ void destroyObjects(Listable*);
+ void destroyObjects(void*);
+
+ void destroyObject(Destroyable* object);
+ void destroyObject(void* object);
+
void updateConfigValues(bool updateChildren, Listable*) const;
void updateConfigValues(bool updateChildren, Identifiable*) const;
@@ -391,6 +401,50 @@
}
/**
+ * @brief Destroy all objects of this class (must be Listable).
+ * Destroyables are destroyed with destroy(), all other classes with delete.
+ */
+ template <class T>
+ void ClassIdentifier<T>::destroyObjects()
+ {
+ this->destroyObjects((T*)0);
+ }
+
+ /**
+ * @brief Only searches and destroys objects if is a @ref Listable
+ */
+ template <class T>
+ void ClassIdentifier<T>::destroyObjects(Listable*)
+ {
+ ObjectListBase* objectList = Context::getRootContext()->getObjectList(this);
+ ObjectListElement<T>* begin = static_cast<ObjectListElement<T>*>(objectList->begin());
+ ObjectListElement<T>* end = static_cast<ObjectListElement<T>*>(objectList->end());
+ for (typename ObjectList<T>::iterator it = begin; it != end; )
+ this->destroyObject(*(it++));
+ }
+
+ template <class T>
+ void ClassIdentifier<T>::destroyObjects(void*)
+ {
+ // no action
+ }
+
+ /**
+ * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types.
+ */
+ template <class T>
+ void ClassIdentifier<T>::destroyObject(Destroyable* object)
+ {
+ object->destroy();
+ }
+
+ template <class T>
+ void ClassIdentifier<T>::destroyObject(void* object)
+ {
+ delete static_cast<Identifiable*>(object);
+ }
+
+ /**
@brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.
*/
template <class T>
Modified: code/branches/core7/src/libraries/core/module/ModuleInstance.h
===================================================================
--- code/branches/core7/src/libraries/core/module/ModuleInstance.h 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/module/ModuleInstance.h 2015-06-07 10:10:24 UTC (rev 10539)
@@ -51,6 +51,9 @@
void loadAllStaticallyInitializedInstances(StaticInitialization::Type type);
void unloadAllStaticallyInitializedInstances(StaticInitialization::Type type);
+ inline const std::set<StaticallyInitializedInstance*>& getInstances(StaticInitialization::Type type)
+ { return this->staticallyInitializedInstancesByType_[type]; }
+
void deleteAllStaticallyInitializedInstances();
inline const std::string& getName() const
Modified: code/branches/core7/src/libraries/core/object/Context.cc
===================================================================
--- code/branches/core7/src/libraries/core/object/Context.cc 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/object/Context.cc 2015-06-07 10:10:24 UTC (rev 10539)
@@ -96,4 +96,11 @@
this->objectLists_[classID] = new ObjectListBase();
return this->objectLists_[classID];
}
+
+ void Context::destroyObjectList(const Identifier* identifier)
+ {
+ ObjectListBase* objectList = this->getObjectList(identifier);
+ delete objectList;
+ this->objectLists_[identifier->getClassID()] = NULL;
+ }
}
Modified: code/branches/core7/src/libraries/core/object/Context.h
===================================================================
--- code/branches/core7/src/libraries/core/object/Context.h 2015-06-07 09:57:31 UTC (rev 10538)
+++ code/branches/core7/src/libraries/core/object/Context.h 2015-06-07 10:10:24 UTC (rev 10539)
@@ -70,6 +70,8 @@
this->getParentContext()->addObject(object);
}
+ void destroyObjectList(const Identifier* identifier);
+
private:
Context* parentContext_;
std::vector<ObjectListBase*> objectLists_;
More information about the Orxonox-commit
mailing list