Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Aug 13, 2013, 11:35:26 PM (11 years ago)
Author:
landauf
Message:

implemented new concept to initialize the class hierarchy: each identifier is initialized individually by creating an object of the corresponding class. identifiers of abstract classes must be told explicitly about their direct parents. this allows to build the class tree correctly also for complicated setups like multiple inheritance of abstract classes.

Location:
code/branches/core6/src/libraries/core/class
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core6/src/libraries/core/class/CMakeLists.txt

    r9577 r9646  
    33  Identifier.cc
    44  IdentifierManager.cc
     5  OrxonoxClass.cc
     6  OrxonoxInterface.cc
    57)
  • code/branches/core6/src/libraries/core/class/Identifiable.cc

    r9574 r9646  
    3535
    3636#include <cassert>
     37#include "core/CoreIncludes.h"
    3738#include "core/object/Context.h"
    3839#include "Identifier.h"
     
    4041namespace orxonox
    4142{
     43    RegisterClassNoArgs(Identifiable);
     44
    4245    /**
    4346        @brief Constructor: Sets the default values.
     
    4649    {
    4750        this->identifier_ = 0;
    48         this->parents_ = 0;
    49         // Optimisation
    50         this->objectPointers_.reserve(6);
    51     }
     51        this->objectPointers_.reserve(6); // Optimisation
    5252
    53     /**
    54         @brief Destructor: Removes the object from the object-lists
    55     */
    56     Identifiable::~Identifiable()
    57     {
    58         // parents_ exists only if isCreatingHierarchy() of the associated Identifier returned true while creating the class
    59         if (this->parents_)
    60             delete this->parents_;
     53        RegisterObject(Identifiable);
    6154    }
    6255
  • code/branches/core6/src/libraries/core/class/Identifiable.h

    r9574 r9646  
    5555        public:
    5656            Identifiable();
    57             virtual ~Identifiable();
     57            virtual ~Identifiable() {}
    5858
    5959            /// Returns the Identifier of the object.
     
    119119        private:
    120120            Identifier* identifier_;               //!< The Identifier of the object
    121             std::set<const Identifier*>* parents_; //!< List of all parents of the object
    122121
    123122            /// 'Fast map' that holds this-pointers of all derived types
  • code/branches/core6/src/libraries/core/class/Identifier.cc

    r9641 r9646  
    3737
    3838#include "util/StringUtils.h"
     39#include "core/CoreIncludes.h"
    3940#include "core/config/ConfigValueContainer.h"
    4041#include "core/XMLPort.h"
     
    5253        : classID_(IdentifierManager::getInstance().getUniqueClassId())
    5354    {
    54         this->bCreatedOneObject_ = false;
    55         this->bSetName_ = false;
    5655        this->factory_ = 0;
     56        this->bInitialized_ = false;
    5757        this->bLoadable_ = false;
    5858
     
    8080
    8181    /**
    82         @brief Registers a class, which means that the name and the parents get stored.
    83         @param parents A list, containing the Identifiers of all parents of the class
    84         @param bRootClass True if the class is either an Interface or the BaseObject itself
    85     */
    86     void Identifier::initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass)
    87     {
    88         // Check if at least one object of the given type was created
    89         if (!this->bCreatedOneObject_ && IdentifierManager::getInstance().isCreatingHierarchy())
    90         {
    91             // If no: We have to store the information and initialize the Identifier
    92             orxout(verbose, context::identifier) << "Register Class in ClassIdentifier<" << this->getName() << ">-Singleton -> Initialize Singleton." << endl;
    93             if (bRootClass)
    94                 this->initialize(0); // If a class is derived from two interfaces, the second interface might think it's derived from the first because of the order of constructor-calls. Thats why we set parents to zero in that case.
    95             else
    96                 this->initialize(parents);
    97         }
    98     }
    99 
    100     /**
    101         @brief Initializes the Identifier with a list containing all parents of the class the Identifier belongs to.
    102         @param parents A list containing all parents
    103     */
    104     void Identifier::initialize(std::set<const Identifier*>* parents)
    105     {
    106         orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << this->name_ << ">-Singleton." << endl;
    107         this->bCreatedOneObject_ = true;
    108 
    109         if (parents)
    110         {
    111             this->parents_ = (*parents);
    112             this->directParents_ = (*parents);
    113 
    114             // Iterate through all parents
    115             for (std::set<const Identifier*>::iterator it = parents->begin(); it != parents->end(); ++it)
    116             {
    117                 // Tell the parent we're one of it's children
    118                 (*it)->children_.insert((*it)->children_.end(), this);
    119 
    120                 // Erase all parents of our parent from our direct-parent-list
    121                 for (std::set<const Identifier*>::const_iterator it1 = (*it)->getParents().begin(); it1 != (*it)->getParents().end(); ++it1)
    122                 {
    123                     // Search for the parent's parent in our direct-parent-list
    124                     for (std::set<const Identifier*>::iterator it2 = this->directParents_.begin(); it2 != this->directParents_.end(); ++it2)
    125                     {
    126                         if ((*it1) == (*it2))
    127                         {
    128                             // We've found a non-direct parent in our list: Erase it
    129                             this->directParents_.erase(it2);
    130                             break;
    131                         }
    132                     }
    133                 }
    134             }
    135 
    136             // Now iterate through all direct parents
    137             for (std::set<const Identifier*>::iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
    138             {
    139                 // Tell the parent we're one of it's direct children
    140                 (*it)->directChildren_.insert((*it)->directChildren_.end(), this);
    141 
    142                 // Create the super-function dependencies
    143                 (*it)->createSuperFunctionCaller();
    144             }
    145         }
    146     }
    147 
    148     /**
    14982        @brief Sets the name of the class.
    15083    */
    15184    void Identifier::setName(const std::string& name)
    15285    {
    153         if (!this->bSetName_)
     86        if (name != this->name_)
    15487        {
    15588            this->name_ = name;
    156             this->bSetName_ = true;
    157             IdentifierManager::getInstance().registerIdentifier(this);
     89            IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
    15890        }
    15991    }
     
    194126    {
    195127        this->networkID_ = id;
    196         IdentifierManager::getInstance().registerIdentifier(this);
     128        IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
     129    }
     130
     131    /**
     132     * @brief Used to define the direct parents of an Identifier of an abstract class.
     133     */
     134    Identifier& Identifier::inheritsFrom(Identifier* directParent)
     135    {
     136        if (this->parents_.empty())
     137            this->directParents_.insert(directParent);
     138        else
     139            orxout(internal_error) << "Trying to add " << directParent->getName() << " as a direct parent of " << this->getName() << " after the latter was already initialized" << endl;
     140
     141        return *this;
     142    }
     143
     144    /**
     145     * @brief Initializes the parents of this Identifier while creating the class hierarchy.
     146     * @param identifiers All identifiers that were used to create an instance of this class (including this identifier itself)
     147     */
     148    void Identifier::initializeParents(const std::set<const Identifier*>& identifiers)
     149    {
     150        if (!IdentifierManager::getInstance().isCreatingHierarchy())
     151        {
     152            orxout(internal_warning) << "Identifier::initializeParents() created outside of class hierarchy creation" << endl;
     153            return;
     154        }
     155
     156        for (std::set<const Identifier*>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it)
     157            if (*it != this)
     158                this->parents_.insert(*it);
     159    }
     160
     161    /**
     162     * @brief Initializes the direct parents of this Identifier while creating the class hierarchy. This is only intended for abstract classes.
     163     */
     164    void Identifier::initializeDirectParentsOfAbstractClass()
     165    {
     166        if (!IdentifierManager::getInstance().isCreatingHierarchy())
     167        {
     168            orxout(internal_warning) << "Identifier::initializeDirectParentsOfAbstractClass() created outside of class hierarchy creation" << endl;
     169            return;
     170        }
     171
     172        // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
     173        if (this->directParents_.empty() && !this->isExactlyA(Class(Identifiable)))
     174        {
     175            orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeidName() << " is marked as abstract but has no direct parents defined" << endl;
     176            orxout(internal_error) << "  If this class is not abstract, use RegisterClass(ThisClass);" << endl;
     177            orxout(internal_error) << "  If this class is abstract, use RegisterAbstractClass(ThisClass).inheritsFrom(Class(BaseClass));" << endl;
     178        }
     179    }
     180
     181    /**
     182     * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
     183     */
     184    void Identifier::finishInitialization()
     185    {
     186        if (!IdentifierManager::getInstance().isCreatingHierarchy())
     187        {
     188            orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
     189            return;
     190        }
     191
     192        if (this->isInitialized())
     193            return;
     194
     195        // if no direct parents were defined, initialize them with the set of all parents
     196        if (this->directParents_.empty())
     197            this->directParents_ = this->parents_;
     198
     199        // initialize all parents before continuing to initialize this identifier
     200        for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     201        {
     202            Identifier* directParent = const_cast<Identifier*>(*it);
     203            directParent->finishInitialization(); // initialize parent
     204            this->parents_.insert(directParent);  // direct parent is also a parent
     205            this->parents_.insert(directParent->parents_.begin(), directParent->parents_.end()); // parents of direct parent are also parents
     206        }
     207
     208        // parents of parents are no direct parents of this identifier
     209        for (std::set<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     210            for (std::set<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     211                this->directParents_.erase(*it_parent_parent);
     212
     213        // tell all parents that this identifier is a child
     214        for (std::set<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     215            const_cast<Identifier*>(*it)->children_.insert(this);
     216
     217        // tell all direct parents that this identifier is a direct child
     218        for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     219        {
     220            const_cast<Identifier*>(*it)->directChildren_.insert(this);
     221
     222            // Create the super-function dependencies
     223            (*it)->createSuperFunctionCaller();
     224        }
     225
     226        this->bInitialized_ = true;
    197227    }
    198228
  • code/branches/core6/src/libraries/core/class/Identifier.h

    r9645 r9646  
    139139            inline void setLoadable(bool bLoadable) { this->bLoadable_ = bLoadable; }
    140140
     141            /// Returns true if the Identifier was completely initialized.
     142            inline bool isInitialized() const { return this->bInitialized_; }
     143
     144
     145            /////////////////////////////
     146            ////// Class Hierarchy //////
     147            /////////////////////////////
     148            Identifier& inheritsFrom(Identifier* directParent);
     149
     150            void initializeParents(const std::set<const Identifier*>& identifiers);
     151            void initializeDirectParentsOfAbstractClass();
     152            void finishInitialization();
     153
    141154            bool isA(const Identifier* identifier) const;
    142155            bool isExactlyA(const Identifier* identifier) const;
     
    146159            bool isDirectParentOf(const Identifier* identifier) const;
    147160
    148 
    149             /////////////////////////////
    150             ////// Class Hierarchy //////
    151             /////////////////////////////
    152161            /// Returns the parents of the class the Identifier belongs to.
    153162            inline const std::set<const Identifier*>& getParents() const { return this->parents_; }
     
    218227            virtual void createSuperFunctionCaller() const = 0;
    219228
    220             void initializeClassHierarchy(std::set<const Identifier*>* parents, bool bRootClass);
    221 
    222             /// Returns the children of the class the Identifier belongs to.
    223             inline std::set<const Identifier*>& getChildrenIntern() const { return this->children_; }
    224             /// Returns the direct children of the class the Identifier belongs to.
    225             inline std::set<const Identifier*>& getDirectChildrenIntern() const { return this->directChildren_; }
    226 
    227229        private:
    228             void initialize(std::set<const Identifier*>* parents);
    229 
    230230            std::set<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to
    231             mutable std::set<const Identifier*> children_;                 //!< The children of the class the Identifier belongs to
     231            std::set<const Identifier*> children_;                         //!< The children of the class the Identifier belongs to
    232232
    233233            std::set<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to
    234             mutable std::set<const Identifier*> directChildren_;           //!< The direct children of the class the Identifier belongs to
    235 
    236             bool bCreatedOneObject_;                                       //!< True if at least one object of the given type was created (used to determine the need of storing the parents)
    237             bool bSetName_;                                                //!< True if the name is set
     234            std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
     235
     236            bool bInitialized_;                                            //!< Is true if the Identifier was completely initialized
    238237            bool bLoadable_;                                               //!< False = it's not permitted to load the object through XML
    239238            std::string name_;                                             //!< The name of the class the Identifier belongs to
     
    277276            static ClassIdentifier<T>* getIdentifier(const std::string& name);
    278277
    279             bool initializeObject(T* object, const std::string& className, bool bRootClass);
     278            bool initializeObject(T* object);
    280279
    281280            void setConfigValues(T* object, Configurable*) const;
     
    351350
    352351        // Get the entry from the map
    353         ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)IdentifierManager::getInstance().getIdentifierSingleton(proposal);
     352        ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)IdentifierManager::getInstance().getGloballyUniqueIdentifier(proposal);
    354353
    355354        if (ClassIdentifier<T>::classIdentifier_s == proposal)
     
    365364        @brief Adds an object of the given type to the ObjectList.
    366365        @param object The object to add
    367         @param className The name of the class T
    368         @param bRootClass True if this is a root class (i.e. it inherits directly from OrxonoxClass)
    369     */
    370     template <class T>
    371     bool ClassIdentifier<T>::initializeObject(T* object, const std::string& className, bool bRootClass)
    372     {
    373         if (bRootClass)
    374             orxout(verbose, context::object_list) << "Register Root-Object: " << className << endl;
    375         else
    376             orxout(verbose, context::object_list) << "Register Object: " << className << endl;
     366    */
     367    template <class T>
     368    bool ClassIdentifier<T>::initializeObject(T* object)
     369    {
     370        orxout(verbose, context::object_list) << "Register Object: " << this->getName() << endl;
    377371
    378372        object->identifier_ = this;
    379373        if (IdentifierManager::getInstance().isCreatingHierarchy())
    380374        {
    381             if (bRootClass && !object->parents_)
    382                 object->parents_ = new std::set<const Identifier*>();
    383 
    384             if (object->parents_)
    385             {
    386                 this->initializeClassHierarchy(object->parents_, bRootClass);
    387                 object->parents_->insert(object->parents_->end(), this);
    388             }
     375            IdentifierManager::getInstance().createdObject(object);
    389376
    390377            this->setConfigValues(object, object);
  • code/branches/core6/src/libraries/core/class/IdentifierManager.cc

    r9644 r9646  
    3737
    3838#include "util/StringUtils.h"
     39#include "core/CoreIncludes.h"
    3940#include "core/config/ConfigValueContainer.h"
    4041#include "core/XMLPort.h"
     
    6061        @return The identifier (unique instance)
    6162    */
    62     Identifier* IdentifierManager::getIdentifierSingleton(Identifier* proposal)
     63    Identifier* IdentifierManager::getGloballyUniqueIdentifier(Identifier* proposal)
    6364    {
    6465        const std::string& typeidName = proposal->getTypeidName();
     
    8182     * Registers the identifier in all maps of the IdentifierManager.
    8283     */
    83     void IdentifierManager::registerIdentifier(Identifier* identifier)
    84     {
    85         IdentifierManager::getInstance().identifierByString_[identifier->getName()] = identifier;
    86         IdentifierManager::getInstance().identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
    87         IdentifierManager::getInstance().identifierByNetworkId_[identifier->getNetworkID()] = identifier;
     84    void IdentifierManager::addIdentifierToLookupMaps(Identifier* identifier)
     85    {
     86        const std::string& typeidName = identifier->getTypeidName();
     87        if (this->identifierByTypeidName_.find(typeidName) != this->identifierByTypeidName_.end())
     88        {
     89            this->identifierByString_[identifier->getName()] = identifier;
     90            this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
     91            this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
     92        }
     93        else
     94            orxout(internal_warning) << "Trying to add an identifier to lookup maps which is not known to IdentifierManager" << endl;
    8895    }
    8996
     
    95102        orxout(internal_status) << "Create class-hierarchy" << endl;
    96103        this->startCreatingHierarchy();
     104
     105        std::set<Identifier*> initializedIdentifiers;
     106
     107        // iterate over all identifiers, create one instance of each class and initialize the identifiers
     108        {
     109            Context temporaryContext(NULL);
     110            for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
     111            {
     112                orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << it->second->getName() << ">-Singleton." << endl;
     113                // To initialize the identifier, we create a new object and delete it afterwards.
     114                if (it->second->hasFactory())
     115                {
     116                    this->identifiersOfNewObject_.clear();
     117                    Identifiable* temp = it->second->fabricate(&temporaryContext);
     118                    if (temp->getIdentifier() != it->second)
     119                        orxout(internal_error) << "Newly created object has unexpected identifier" << endl;
     120                    delete temp;
     121
     122                    it->second->initializeParents(this->identifiersOfNewObject_);
     123                }
     124                else
     125                    it->second->initializeDirectParentsOfAbstractClass();
     126
     127                initializedIdentifiers.insert(it->second);
     128            }
     129        }
     130
     131        // finish the initialization of all identifiers
    97132        for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
    98133        {
    99             // To create the new branch of the class-hierarchy, we create a new object and delete it afterwards.
    100             if (it->second->hasFactory())
    101             {
    102                 Identifiable* temp = it->second->fabricate(0);
    103                 delete temp;
    104             }
    105         }
     134            if (initializedIdentifiers.find(it->second) != initializedIdentifiers.end())
     135                it->second->finishInitialization();
     136            else
     137                orxout(internal_error) << "Identifier was registered late and is not initialized: " << it->second->getName() << " / " << it->second->getTypeidName() << endl;
     138        }
     139
    106140        this->stopCreatingHierarchy();
    107141        orxout(internal_status) << "Finished class-hierarchy creation" << endl;
     
    123157
    124158    /**
     159     * @brief Notifies the IdentifierManager about a newly created object while creating the class hierarchy.
     160     */
     161    void IdentifierManager::createdObject(Identifiable* identifiable)
     162    {
     163        if (this->isCreatingHierarchy())
     164            this->identifiersOfNewObject_.insert(identifiable->getIdentifier());
     165        else
     166            orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl;
     167    }
     168
     169    /**
    125170        @brief Returns the Identifier with a given name.
    126171        @param name The name of the wanted Identifier
  • code/branches/core6/src/libraries/core/class/IdentifierManager.h

    r9644 r9646  
    3838
    3939#include <map>
     40#include <set>
    4041#include <string>
    4142
     
    4748            static IdentifierManager& getInstance();
    4849
    49             Identifier* getIdentifierSingleton(Identifier* proposal);
    50             void registerIdentifier(Identifier* identifier);
     50            Identifier* getGloballyUniqueIdentifier(Identifier* proposal);
     51            void addIdentifierToLookupMaps(Identifier* identifier);
    5152
    5253            unsigned int getUniqueClassId()
     
    5960            void createClassHierarchy();
    6061            void destroyAllIdentifiers();
     62
     63            void createdObject(Identifiable* identifiable);
    6164
    6265            /// Returns true, if a branch of the class-hierarchy is being created, causing all new objects to store their parents.
     
    103106
    104107            int hierarchyCreatingCounter_s;                         //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading)
     108            std::set<const Identifier*> identifiersOfNewObject_;    //!< Used while creating the object hierarchy to keep track of the identifiers of a newly created object
    105109            unsigned int classIDCounter_s;                          //!< counter for the unique classIDs
    106110    };
  • code/branches/core6/src/libraries/core/class/OrxonoxClass.h

    r9607 r9646  
    5353    class _CoreExport OrxonoxClass : virtual public Configurable, virtual public Destroyable
    5454    {
     55        public:
     56            OrxonoxClass();
    5557    };
    5658}
  • code/branches/core6/src/libraries/core/class/OrxonoxInterface.h

    r9585 r9646  
    5050    class _CoreExport OrxonoxInterface : virtual public Configurable, virtual public Destroyable
    5151    {
     52        public:
     53            OrxonoxInterface();
    5254    };
    5355}
  • code/branches/core6/src/libraries/core/class/Super.h

    r9568 r9646  
    103103            { \
    104104                ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier(); \
    105                 for (std::set<const Identifier*>::iterator it = identifier->getDirectChildrenIntern().begin(); it != identifier->getDirectChildrenIntern().end(); ++it) \
     105                for (std::set<const Identifier*>::iterator it = identifier->getDirectChildren().begin(); it != identifier->getDirectChildren().end(); ++it) \
    106106                { \
    107107                    if (((ClassIdentifier<T>*)(*it))->bSuperFunctionCaller_##functionname##_isFallback_ && ((ClassIdentifier<T>*)(*it))->superFunctionCaller_##functionname##_) \
     
    171171
    172172                // Iterate through all children
    173                 for (std::set<const Identifier*>::iterator it = identifier->getDirectChildrenIntern().begin(); it != identifier->getDirectChildrenIntern().end(); ++it)
     173                for (std::set<const Identifier*>::iterator it = identifier->getDirectChildren().begin(); it != identifier->getDirectChildren().end(); ++it)
    174174                {
    175175                    // Check if the caller is a fallback-caller
Note: See TracChangeset for help on using the changeset viewer.