- Timestamp:
- Oct 4, 2015, 9:12:21 PM (10 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
-
code/trunk/src/libraries/core/class/IdentifierManager.cc
r9667 r10624 37 37 38 38 #include "util/StringUtils.h" 39 #include "core/Core Includes.h"39 #include "core/Core.h" 40 40 #include "core/config/ConfigValueContainer.h" 41 41 #include "core/XMLPort.h" … … 44 44 namespace orxonox 45 45 { 46 /* static */ IdentifierManager& IdentifierManager::getInstance() 47 { 48 static IdentifierManager instance; 49 return instance; 50 } 46 IdentifierManager* IdentifierManager::singletonPtr_s = 0; 51 47 52 48 IdentifierManager::IdentifierManager() 53 49 { 54 50 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; 79 52 } 80 53 … … 82 55 * Registers the identifier in all maps of the IdentifierManager. 83 56 */ 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()); 95 76 } 96 77 … … 112 93 { 113 94 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) 115 96 { 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; 117 102 // To initialize the identifier, we create a new object and delete it afterwards. 118 if (i t->second->hasFactory())103 if (identifier->hasFactory()) 119 104 { 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 124 117 delete temp; 125 126 it->second->initializeParents(this->identifiersOfNewObject_);127 118 } 128 else 129 it->second->initializeDirectParentsOfAbstractClass(); 130 131 initializedIdentifiers.insert(it->second); 119 120 initializedIdentifiers.insert(identifier); 132 121 } 133 122 … … 138 127 139 128 // 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); 147 135 148 136 this->stopCreatingHierarchy(); … … 151 139 152 140 /** 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(); 164 188 } 165 189 … … 170 194 { 171 195 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 } 173 208 else 174 209 orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl; … … 218 253 219 254 /** 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 /** 220 269 @brief Cleans the NetworkID map (needed on clients for correct initialization) 221 270 */
Note: See TracChangeset
for help on using the changeset viewer.