Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 4, 2015, 9:12:21 PM (9 years ago)
Author:
landauf
Message:

merged branch core7 back to trunk

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/core/class/IdentifierManager.cc

    r9667 r10624  
    3737
    3838#include "util/StringUtils.h"
    39 #include "core/CoreIncludes.h"
     39#include "core/Core.h"
    4040#include "core/config/ConfigValueContainer.h"
    4141#include "core/XMLPort.h"
     
    4444namespace orxonox
    4545{
    46     /* static */ IdentifierManager& IdentifierManager::getInstance()
    47     {
    48         static IdentifierManager instance;
    49         return instance;
    50     }
     46    IdentifierManager* IdentifierManager::singletonPtr_s = 0;
    5147
    5248    IdentifierManager::IdentifierManager()
    5349    {
    5450        this->hierarchyCreatingCounter_s = 0;
    55         this->classIDCounter_s = 0;
    56     }
    57 
    58     /**
    59         @brief Returns an identifier by name and adds it if not available
    60         @param proposal A pointer to a newly created identifier for the case of non existence in the map
    61         @return The identifier (unique instance)
    62     */
    63     Identifier* IdentifierManager::getGloballyUniqueIdentifier(Identifier* proposal)
    64     {
    65         const std::string& typeidName = proposal->getTypeidName();
    66         std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.find(typeidName);
    67 
    68         if (it != this->identifierByTypeidName_.end())
    69         {
    70             // There is already an entry: return it
    71             return it->second;
    72         }
    73         else
    74         {
    75             // There is no entry: put the proposal into the map and return it
    76             this->identifierByTypeidName_[typeidName] = proposal;
    77             return proposal;
    78         }
     51        this->recordTraceForIdentifier_ = NULL;
    7952    }
    8053
     
    8255     * Registers the identifier in all maps of the IdentifierManager.
    8356     */
    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;
     57    void IdentifierManager::addIdentifier(Identifier* identifier)
     58    {
     59        orxout(verbose, context::identifier) << "Adding identifier for " << identifier->getName() << " / " << identifier->getTypeInfo().name() << endl;
     60
     61        this->identifiers_.insert(identifier);
     62        this->identifierByString_[identifier->getName()] = identifier;
     63        this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
     64        this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
     65    }
     66
     67    /**
     68     * Unregisters the identifier from all maps of the IdentifierManager.
     69     */
     70    void IdentifierManager::removeIdentifier(Identifier* identifier)
     71    {
     72        this->identifiers_.erase(identifier);
     73        this->identifierByString_.erase(identifier->getName());
     74        this->identifierByLowercaseString_.erase(getLowercase(identifier->getName()));
     75        this->identifierByNetworkId_.erase(identifier->getNetworkID());
    9576    }
    9677
     
    11293        {
    11394            Context temporaryContext(NULL);
    114             for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
     95            for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
    11596            {
    116                 orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << it->second->getName() << ">-Singleton." << endl;
     97                Identifier* identifier = (*it);
     98                if (identifier->isInitialized())
     99                    continue;
     100
     101                orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << identifier->getName() << ">-Singleton." << endl;
    117102                // To initialize the identifier, we create a new object and delete it afterwards.
    118                 if (it->second->hasFactory())
     103                if (identifier->hasFactory())
    119104                {
    120                     this->identifiersOfNewObject_.clear();
    121                     Identifiable* temp = it->second->fabricate(&temporaryContext);
    122                     if (temp->getIdentifier() != it->second)
    123                         orxout(internal_error) << "Newly created object of type " << it->second->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
     105                    this->identifierTraceOfNewObject_.clear();
     106                    this->recordTraceForIdentifier_ = identifier;
     107
     108                    Identifiable* temp = identifier->fabricate(&temporaryContext);
     109
     110                    this->recordTraceForIdentifier_ = NULL;
     111
     112                    if (temp->getIdentifier() != identifier)
     113                        orxout(internal_error) << "Newly created object of type " << identifier->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
     114
     115                    identifier->initializeParents(this->identifierTraceOfNewObject_[temp]);
     116
    124117                    delete temp;
    125 
    126                     it->second->initializeParents(this->identifiersOfNewObject_);
    127118                }
    128                 else
    129                     it->second->initializeDirectParentsOfAbstractClass();
    130 
    131                 initializedIdentifiers.insert(it->second);
     119
     120                initializedIdentifiers.insert(identifier);
    132121            }
    133122
     
    138127
    139128        // finish the initialization of all identifiers
    140         for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
    141         {
    142             if (initializedIdentifiers.find(it->second) != initializedIdentifiers.end())
    143                 it->second->finishInitialization();
    144             else
    145                 orxout(internal_error) << "Identifier was registered late and is not initialized: " << it->second->getName() << " / " << it->second->getTypeidName() << endl;
    146         }
     129        for (std::set<Identifier*>::const_iterator it = initializedIdentifiers.begin(); it != initializedIdentifiers.end(); ++it)
     130            (*it)->finishInitialization();
     131
     132        // only check class hierarchy in dev mode because it's an expensive operation and it requires a developer to fix detected problems anyway.
     133        if (!Core::exists() || Core::getInstance().getConfig()->inDevMode())
     134            this->verifyClassHierarchy(initializedIdentifiers);
    147135
    148136        this->stopCreatingHierarchy();
     
    151139
    152140    /**
    153         @brief Destroys all Identifiers. Called when exiting the program.
    154     */
    155     void IdentifierManager::destroyAllIdentifiers()
    156     {
    157         for (std::map<std::string, Identifier*>::iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
    158             delete (it->second);
    159 
    160         this->identifierByTypeidName_.clear();
    161         this->identifierByString_.clear();
    162         this->identifierByLowercaseString_.clear();
    163         this->identifierByNetworkId_.clear();
     141     * Verifies if the class hierarchy is consistent with the RTTI.
     142     */
     143    void IdentifierManager::verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers)
     144    {
     145        // check if there are any uninitialized identifiers remaining
     146        for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     147            if (!(*it)->isInitialized())
     148                orxout(internal_error) << "Identifier was registered late and is not initialized: " << (*it)->getName() << " / " << (*it)->getTypeInfo().name() << endl;
     149
     150        // for all initialized identifiers, check if a sample instance behaves as expected according to the class hierarchy
     151        Context temporaryContext(NULL);
     152        for (std::set<Identifier*>::const_iterator it1 = initializedIdentifiers.begin(); it1 != initializedIdentifiers.end(); ++it1)
     153        {
     154            if (!(*it1)->hasFactory())
     155                continue;
     156
     157            Identifiable* temp = (*it1)->fabricate(&temporaryContext);
     158
     159            for (std::set<Identifier*>::const_iterator it2 = this->identifiers_.begin(); it2 != this->identifiers_.end(); ++it2)
     160            {
     161                bool isA_AccordingToRtti = (*it2)->canDynamicCastObjectToIdentifierClass(temp);
     162                bool isA_AccordingToClassHierarchy = temp->isA((*it2));
     163
     164                if (isA_AccordingToRtti != isA_AccordingToClassHierarchy)
     165                {
     166                    orxout(internal_error) << "Class hierarchy does not match RTTI: Class hierarchy claims that " << (*it1)->getName() <<
     167                        (isA_AccordingToClassHierarchy ? " is a " : " is not a ") << (*it2)->getName() << " but RTTI says the opposite." << endl;
     168                }
     169            }
     170
     171            delete temp;
     172        }
     173        orxout(internal_info) << "Class hierarchy matches RTTI" << endl;
     174
     175        size_t numberOfObjects = temporaryContext.getObjectList<Listable>()->size();
     176        if (numberOfObjects > 0)
     177            orxout(internal_warning) << "There are still " << numberOfObjects << " listables left after creating the class hierarchy" << endl;
     178    }
     179
     180    /**
     181     * @brief Resets all Identifiers.
     182     */
     183    void IdentifierManager::destroyClassHierarchy()
     184    {
     185        orxout(internal_status) << "Destroy class-hierarchy" << endl;
     186        for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     187            (*it)->reset();
    164188    }
    165189
     
    170194    {
    171195        if (this->isCreatingHierarchy())
    172             this->identifiersOfNewObject_.insert(identifiable->getIdentifier());
     196        {
     197            if (this->recordTraceForIdentifier_)
     198            {
     199                std::list<const Identifier*>& traceForObject = this->identifierTraceOfNewObject_[identifiable];
     200                if (std::find(traceForObject.begin(), traceForObject.end(), identifiable->getIdentifier()) != traceForObject.end())
     201                {
     202                    orxout(internal_warning) << this->recordTraceForIdentifier_->getName() << " inherits two times from " <<
     203                        identifiable->getIdentifier()->getName() << ". Did you forget to use virtual inheritance?" << endl;
     204                }
     205                traceForObject.push_back(identifiable->getIdentifier());
     206            }
     207        }
    173208        else
    174209            orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl;
     
    218253
    219254    /**
     255        @brief Returns the Identifier with a given typeid-name.
     256        @param name The typeid-name of the wanted Identifier
     257        @return The Identifier
     258    */
     259    Identifier* IdentifierManager::getIdentifierByTypeInfo(const std::type_info& typeInfo)
     260    {
     261        // TODO: use std::type_index and a map to find identifiers by type_info (only with c++11)
     262        for (std::set<Identifier*>::iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     263            if ((*it)->getTypeInfo() == typeInfo)
     264                return (*it);
     265        return 0;
     266    }
     267
     268    /**
    220269        @brief Cleans the NetworkID map (needed on clients for correct initialization)
    221270    */
Note: See TracChangeset for help on using the changeset viewer.