Changeset 10624 for code/trunk/src/libraries/core/class
- Timestamp:
- Oct 4, 2015, 9:12:21 PM (9 years ago)
- Location:
- code/trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
-
code/trunk/src/libraries/core/class/Identifiable.cc
r9667 r10624 41 41 namespace orxonox 42 42 { 43 RegisterClassNoArgs(Identifiable) ;43 RegisterClassNoArgs(Identifiable).virtualBase(); 44 44 45 45 /** -
code/trunk/src/libraries/core/class/Identifier.cc
r9667 r10624 44 44 namespace orxonox 45 45 { 46 bool Identifier::initConfigValues_s = true; 47 46 48 // ############################### 47 49 // ### Identifier ### … … 50 52 @brief Constructor: No factory, no object created, new ObjectList and a unique networkID. 51 53 */ 52 Identifier::Identifier() 53 : classID_(IdentifierManager::getInstance().getUniqueClassId()) 54 { 55 this->factory_ = 0; 54 Identifier::Identifier(const std::string& name, Factory* factory, bool bLoadable) 55 { 56 orxout(verbose, context::identifier) << "Create identifier for " << name << endl; 57 58 static unsigned int classIDCounter = 0; 59 60 this->classID_ = classIDCounter++; 61 this->name_ = name; 62 this->factory_ = factory; 63 this->bLoadable_ = bLoadable; 56 64 this->bInitialized_ = false; 57 this->b Loadable_ = false;65 this->bIsVirtualBase_ = false; 58 66 59 67 this->bHasConfigValues_ = false; … … 71 79 delete this->factory_; 72 80 81 for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it) 82 delete (*it); 83 84 // erase this Identifier from all related identifiers 85 for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it) 86 const_cast<Identifier*>(*it)->children_.erase(this); 87 for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it) 88 const_cast<Identifier*>(*it)->directChildren_.erase(this); 89 for (std::set<const Identifier*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it) 90 const_cast<Identifier*>(*it)->parents_.remove(this); 91 for (std::set<const Identifier*>::const_iterator it = this->directChildren_.begin(); it != this->directChildren_.end(); ++it) 92 const_cast<Identifier*>(*it)->directParents_.remove(this); 93 73 94 for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it) 74 95 delete (it->second); … … 77 98 for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it) 78 99 delete (it->second); 79 }80 81 /**82 @brief Sets the name of the class.83 */84 void Identifier::setName(const std::string& name)85 {86 if (name != this->name_)87 {88 this->name_ = name;89 IdentifierManager::getInstance().addIdentifierToLookupMaps(this);90 }91 }92 93 void Identifier::setFactory(Factory* factory)94 {95 if (this->factory_)96 delete this->factory_;97 98 this->factory_ = factory;99 100 } 100 101 … … 126 127 { 127 128 this->networkID_ = id; 128 IdentifierManager::getInstance().addIdentifier ToLookupMaps(this);129 IdentifierManager::getInstance().addIdentifier(this); // add with new id 129 130 } 130 131 … … 132 133 * @brief Used to define the direct parents of an Identifier of an abstract class. 133 134 */ 134 Identifier& Identifier::inheritsFrom(I dentifier* directParent)135 { 136 if (this-> parents_.empty())137 this-> directParents_.insert(directParent);138 else 139 orxout(internal_error) << "Trying to add " << directParent->getName() << " as adirect parent of " << this->getName() << " after the latter was already initialized" << endl;135 Identifier& Identifier::inheritsFrom(InheritsFrom* directParent) 136 { 137 if (this->directParents_.empty()) 138 this->manualDirectParents_.push_back(directParent); 139 else 140 orxout(internal_error) << "Trying to manually add direct parent of " << this->getName() << " after the latter was already initialized" << endl; 140 141 141 142 return *this; … … 144 145 /** 145 146 * @brief Initializes the parents of this Identifier while creating the class hierarchy. 146 * @param i dentifiers All identifiers that were used to create an instance of this class (includingthis identifier itself)147 */ 148 void Identifier::initializeParents(const std:: set<const Identifier*>& identifiers)147 * @param initializationTrace All identifiers that were recorded while creating an instance of this class (including nested classes and this identifier itself) 148 */ 149 void Identifier::initializeParents(const std::list<const Identifier*>& initializationTrace) 149 150 { 150 151 if (!IdentifierManager::getInstance().isCreatingHierarchy()) … … 154 155 } 155 156 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() 157 if (this->directParents_.empty()) 158 { 159 for (std::list<const Identifier*>::const_iterator it = initializationTrace.begin(); it != initializationTrace.end(); ++it) 160 if (*it != this) 161 this->parents_.push_back(*it); 162 } 163 else 164 orxout(internal_error) << "Trying to add parents to " << this->getName() << " after it was already initialized with manual calls to inheritsFrom<Class>()." << endl; 165 } 166 167 /** 168 * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly. 169 */ 170 void Identifier::finishInitialization() 165 171 { 166 172 if (!IdentifierManager::getInstance().isCreatingHierarchy()) 167 173 { 168 orxout(internal_warning) << "Identifier:: initializeDirectParentsOfAbstractClass() created outside of class hierarchy creation" << endl;174 orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl; 169 175 return; 170 176 } 171 177 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; 178 if (this->isInitialized()) 179 return; 180 181 if (!this->parents_.empty()) 182 { 183 // parents defined -> this class was initialized by creating a sample instance and recording the trace of identifiers 184 185 // initialize all parents 186 for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it) 187 const_cast<Identifier*>(*it)->finishInitialization(); // initialize parent 188 189 // parents of parents are no direct parents of this identifier 190 this->directParents_ = this->parents_; 191 for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent) 192 for (std::list<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) 193 this->directParents_.remove(*it_parent_parent); 194 195 this->verifyIdentifierTrace(); 196 } 197 else if (!this->manualDirectParents_.empty()) 198 { 199 // no parents defined -> this class was manually initialized by calling inheritsFrom<Class>() 200 201 // initialize all direct parents 202 for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it) 203 { 204 Identifier* directParent = (*it)->getParent(); 205 this->directParents_.push_back(directParent); 206 directParent->finishInitialization(); // initialize parent 207 } 208 209 // direct parents and their parents are also parents of this identifier (but only add them once) 210 for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent) 211 { 212 for (std::list<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) 213 this->addIfNotExists(this->parents_, *it_parent_parent); 214 this->addIfNotExists(this->parents_, *it_parent); 215 } 216 } 217 else if (!this->isExactlyA(Class(Identifiable))) 218 { 219 // only Identifiable is allowed to have no parents (even tough it's currently not abstract) 220 orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeInfo().name() << " is marked as abstract but has no direct parents defined" << endl; 176 221 orxout(internal_error) << " If this class is not abstract, use RegisterClass(ThisClass);" << endl; 177 222 orxout(internal_error) << " If this class is abstract, use RegisterAbstractClass(ThisClass).inheritsFrom(Class(BaseClass));" << endl; 178 223 } 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 parents196 if (this->directParents_.empty())197 this->directParents_ = this->parents_;198 199 // initialize all parents before continuing to initialize this identifier200 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 parent204 this->parents_.insert(directParent); // direct parent is also a parent205 this->parents_.insert(directParent->parents_.begin(), directParent->parents_.end()); // parents of direct parent are also parents206 }207 208 // parents of parents are no direct parents of this identifier209 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 224 213 225 // 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)226 for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it) 215 227 const_cast<Identifier*>(*it)->children_.insert(this); 216 228 217 229 // 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)230 for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it) 219 231 { 220 232 const_cast<Identifier*>(*it)->directChildren_.insert(this); … … 228 240 229 241 /** 242 * Resets all information about the class hierarchy. The identifier is considered uninitialized afterwards. 243 */ 244 void Identifier::reset() 245 { 246 this->directParents_.clear(); 247 this->parents_.clear(); 248 this->directChildren_.clear(); 249 this->children_.clear(); 250 this->bInitialized_ = false; 251 } 252 253 /** 254 * Verifies if the recorded trace of parent identifiers matches the expected trace according to the class hierarchy. If it doesn't match, the class 255 * hierarchy is likely wrong, e.g. due to wrong inheritsFrom<>() definitions in abstract classes. 256 */ 257 void Identifier::verifyIdentifierTrace() const 258 { 259 260 std::list<const Identifier*> expectedIdentifierTrace; 261 262 // if any parent class is virtual, it will be instantiated first, so we need to add them first. 263 for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent) 264 { 265 if ((*it_parent)->isVirtualBase()) 266 { 267 for (std::list<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) 268 this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent); 269 this->addIfNotExists(expectedIdentifierTrace, *it_parent); 270 } 271 } 272 273 // now all direct parents get created recursively. already added identifiers (e.g. virtual base classes) are not added again. 274 for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent) 275 { 276 for (std::list<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) 277 this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent); 278 this->addIfNotExists(expectedIdentifierTrace, *it_parent); 279 } 280 281 // check if the expected trace matches the actual trace (which was defined by creating a sample instance) 282 if (expectedIdentifierTrace != this->parents_) 283 { 284 orxout(internal_warning) << this->getName() << " has an unexpected initialization trace:" << endl; 285 286 orxout(internal_warning) << " Actual trace (after creating a sample instance):" << endl << " "; 287 for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent) 288 orxout(internal_warning) << " " << (*it_parent)->getName(); 289 orxout(internal_warning) << endl; 290 291 orxout(internal_warning) << " Expected trace (according to class hierarchy definitions):" << endl << " "; 292 for (std::list<const Identifier*>::const_iterator it_parent = expectedIdentifierTrace.begin(); it_parent != expectedIdentifierTrace.end(); ++it_parent) 293 orxout(internal_warning) << " " << (*it_parent)->getName(); 294 orxout(internal_warning) << endl; 295 296 orxout(internal_warning) << " Direct parents (according to class hierarchy definitions):" << endl << " "; 297 for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent) 298 orxout(internal_warning) << " " << (*it_parent)->getName(); 299 orxout(internal_warning) << endl; 300 } 301 } 302 303 /** 304 * Adds @param identifierToAdd to @param list if this identifier is not already contained in the list. 305 */ 306 void Identifier::addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const 307 { 308 if (std::find(list.begin(), list.end(), identifierToAdd) == list.end()) 309 list.push_back(identifierToAdd); 310 } 311 312 /** 230 313 @brief Returns true, if the Identifier is at least of the given type. 231 314 @param identifier The identifier to compare with … … 233 316 bool Identifier::isA(const Identifier* identifier) const 234 317 { 235 return (identifier == this || (this-> parents_.find(identifier) != this->parents_.end()));318 return (identifier == this || (this->isChildOf(identifier))); 236 319 } 237 320 … … 251 334 bool Identifier::isChildOf(const Identifier* identifier) const 252 335 { 253 return ( this->parents_.find(identifier) != this->parents_.end());336 return (std::find(this->parents_.begin(), this->parents_.end(), identifier) != this->parents_.end()); 254 337 } 255 338 … … 260 343 bool Identifier::isDirectChildOf(const Identifier* identifier) const 261 344 { 262 return ( this->directParents_.find(identifier) != this->directParents_.end());345 return (std::find(this->directParents_.begin(), this->directParents_.end(), identifier) != this->directParents_.end()); 263 346 } 264 347 -
code/trunk/src/libraries/core/class/Identifier.h
r9667 r10624 80 80 #include <typeinfo> 81 81 #include <loki/TypeTraits.h> 82 #include <boost/static_assert.hpp> 83 #include <boost/type_traits/is_base_of.hpp> 82 84 83 85 #include "util/Output.h" 86 #include "util/OrxAssert.h" 84 87 #include "core/object/ObjectList.h" 85 88 #include "core/object/Listable.h" … … 109 112 { 110 113 public: 111 Identifier(); 114 struct InheritsFrom //! helper class to manually define inheritance 115 { 116 virtual ~InheritsFrom() {} 117 virtual Identifier* getParent() const = 0; 118 }; 119 120 public: 121 Identifier(const std::string& name, Factory* factory, bool bLoadable); 112 122 Identifier(const Identifier& identifier); // don't copy 113 123 virtual ~Identifier(); … … 115 125 /// Returns the name of the class the Identifier belongs to. 116 126 inline const std::string& getName() const { return this->name_; } 117 void setName(const std::string& name); 118 119 /// Returns the name of the class as it is returned by typeid(T).name() 120 virtual const std::string& getTypeidName() = 0; 127 128 /// Returns the type_info of the class as it is returned by typeid(T) 129 virtual const std::type_info& getTypeInfo() = 0; 121 130 122 131 /// Returns the network ID to identify a class through the network. … … 127 136 ORX_FORCEINLINE unsigned int getClassID() const { return this->classID_; } 128 137 129 /// Sets the Factory.130 void setFactory(Factory* factory);131 138 /// Returns true if the Identifier has a Factory. 132 139 inline bool hasFactory() const { return (this->factory_ != 0); } … … 136 143 /// Returns true if the class can be loaded through XML. 137 144 inline bool isLoadable() const { return this->bLoadable_; } 138 /// Set the class to be loadable through XML or not. 139 inline void setLoadable(bool bLoadable) { this->bLoadable_ = bLoadable; } 145 146 /// Returns true if child classes should inherit virtually from this class. 147 inline bool isVirtualBase() const { return this->bIsVirtualBase_; } 148 /// Defines if child classes should inherit virtually from this class. 149 inline void setVirtualBase(bool bIsVirtualBase) { this->bIsVirtualBase_ = bIsVirtualBase; } 140 150 141 151 /// Returns true if the Identifier was completely initialized. 142 152 inline bool isInitialized() const { return this->bInitialized_; } 153 154 virtual void destroyObjects() = 0; 155 156 virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0; 157 158 static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible 143 159 144 160 … … 146 162 ////// Class Hierarchy ////// 147 163 ///////////////////////////// 148 Identifier& inheritsFrom(Identifier* directParent); 149 150 void initializeParents(const std::set<const Identifier*>& identifiers); 151 void initializeDirectParentsOfAbstractClass(); 164 Identifier& inheritsFrom(InheritsFrom* directParent); 165 166 void initializeParents(const std::list<const Identifier*>& initializationTrace); 152 167 void finishInitialization(); 168 void reset(); 153 169 154 170 bool isA(const Identifier* identifier) const; … … 159 175 bool isDirectParentOf(const Identifier* identifier) const; 160 176 177 /// Returns the direct parents of the class the Identifier belongs to. 178 inline const std::list<const Identifier*>& getDirectParents() const { return this->directParents_; } 161 179 /// Returns the parents of the class the Identifier belongs to. 162 inline const std::set<const Identifier*>& getParents() const { return this->parents_; } 163 /// Returns the begin-iterator of the parents-list. 164 inline std::set<const Identifier*>::const_iterator getParentsBegin() const { return this->parents_.begin(); } 165 /// Returns the end-iterator of the parents-list. 166 inline std::set<const Identifier*>::const_iterator getParentsEnd() const { return this->parents_.end(); } 167 180 inline const std::list<const Identifier*>& getParents() const { return this->parents_; } 181 182 /// Returns the direct children the class the Identifier belongs to. 183 inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; } 168 184 /// Returns the children of the class the Identifier belongs to. 169 185 inline const std::set<const Identifier*>& getChildren() const { return this->children_; } 170 /// Returns the begin-iterator of the children-list.171 inline std::set<const Identifier*>::const_iterator getChildrenBegin() const { return this->children_.begin(); }172 /// Returns the end-iterator of the children-list.173 inline std::set<const Identifier*>::const_iterator getChildrenEnd() const { return this->children_.end(); }174 175 /// Returns the direct parents of the class the Identifier belongs to.176 inline const std::set<const Identifier*>& getDirectParents() const { return this->directParents_; }177 /// Returns the begin-iterator of the direct-parents-list.178 inline std::set<const Identifier*>::const_iterator getDirectParentsBegin() const { return this->directParents_.begin(); }179 /// Returns the end-iterator of the direct-parents-list.180 inline std::set<const Identifier*>::const_iterator getDirectParentsEnd() const { return this->directParents_.end(); }181 182 /// Returns the direct children the class the Identifier belongs to.183 inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }184 /// Returns the begin-iterator of the direct-children-list.185 inline std::set<const Identifier*>::const_iterator getDirectChildrenBegin() const { return this->directChildren_.begin(); }186 /// Returns the end-iterator of the direct-children-list.187 inline std::set<const Identifier*>::const_iterator getDirectChildrenEnd() const { return this->directChildren_.end(); }188 186 189 187 … … 223 221 XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname); 224 222 225 226 223 protected: 227 224 virtual void createSuperFunctionCaller() const = 0; 228 225 229 226 private: 230 std::set<const Identifier*> parents_; //!< The parents of the class the Identifier belongs to 227 void verifyIdentifierTrace() const; 228 void addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const; 229 230 std::list<const InheritsFrom*> manualDirectParents_; //!< Manually defined direct parents 231 std::list<const Identifier*> directParents_; //!< The direct parents of the class the Identifier belongs to (sorted by their order of initialization) 232 std::list<const Identifier*> parents_; //!< The parents of the class the Identifier belongs to (sorted by their order of initialization) 233 234 std::set<const Identifier*> directChildren_; //!< The direct children of the class the Identifier belongs to 231 235 std::set<const Identifier*> children_; //!< The children of the class the Identifier belongs to 232 233 std::set<const Identifier*> directParents_; //!< The direct parents of the class the Identifier belongs to234 std::set<const Identifier*> directChildren_; //!< The direct children of the class the Identifier belongs to235 236 236 237 bool bInitialized_; //!< Is true if the Identifier was completely initialized 237 238 bool bLoadable_; //!< False = it's not permitted to load the object through XML 239 bool bIsVirtualBase_; //!< If true, it is recommended to inherit virtually from this class. This changes the order of initialization of child classes, thus this information is necessary to check the class hierarchy. 238 240 std::string name_; //!< The name of the class the Identifier belongs to 239 241 Factory* factory_; //!< The Factory, able to create new objects of the given class (if available) 240 242 uint32_t networkID_; //!< The network ID to identify a class through the network 241 const unsigned int classID_;//!< Uniquely identifies a class (might not be the same as the networkID_)243 unsigned int classID_; //!< Uniquely identifies a class (might not be the same as the networkID_) 242 244 243 245 bool bHasConfigValues_; //!< True if this class has at least one assigned config value … … 267 269 class ClassIdentifier : public Identifier 268 270 { 271 BOOST_STATIC_ASSERT((boost::is_base_of<Identifiable, T>::value)); 272 269 273 #ifndef DOXYGEN_SHOULD_SKIP_THIS 270 274 #define SUPER_INTRUSIVE_DECLARATION_INCLUDE … … 273 277 274 278 public: 275 static ClassIdentifier<T>* getIdentifier(); 276 static ClassIdentifier<T>* getIdentifier(const std::string& name); 277 278 bool initializeObject(T* object); 279 280 void setConfigValues(T* object, Configurable*) const; 281 void setConfigValues(T* object, Identifiable*) const; 282 283 void addObjectToList(T* object, Listable*); 284 void addObjectToList(T* object, Identifiable*); 285 286 virtual void updateConfigValues(bool updateChildren = true) const; 287 288 virtual const std::string& getTypeidName() 289 { return this->typeidName_; } 290 291 private: 292 static void initializeIdentifier(); 293 294 ClassIdentifier(const ClassIdentifier<T>& identifier) {} // don't copy 295 ClassIdentifier() 279 ClassIdentifier(const std::string& name, Factory* factory, bool bLoadable) : Identifier(name, factory, bLoadable) 296 280 { 297 this->typeidName_ = typeid(T).name(); 281 OrxVerify(ClassIdentifier<T>::classIdentifier_s == NULL, "Assertion failed in ClassIdentifier of type " << typeid(T).name()); 282 ClassIdentifier<T>::classIdentifier_s = this; 283 298 284 SuperFunctionInitialization<0, T>::initialize(this); 299 285 } … … 303 289 } 304 290 291 bool initializeObject(T* object); 292 293 virtual void updateConfigValues(bool updateChildren = true) const; 294 295 virtual const std::type_info& getTypeInfo() 296 { return typeid(T); } 297 298 virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const 299 { return dynamic_cast<T*>(object) != 0; } 300 301 virtual void destroyObjects(); 302 303 static ClassIdentifier<T>* getIdentifier(); 304 305 private: 306 ClassIdentifier(const ClassIdentifier<T>& identifier) {} // don't copy 307 308 void setConfigValues(T* object, Configurable*) const; 309 void setConfigValues(T* object, Identifiable*) const; 310 311 void addObjectToList(T* object, Listable*); 312 void addObjectToList(T* object, Identifiable*); 313 314 void destroyObjects(Listable*); 315 void destroyObjects(void*); 316 317 void destroyObject(Destroyable* object); 318 void destroyObject(void* object); 319 305 320 void updateConfigValues(bool updateChildren, Listable*) const; 306 321 void updateConfigValues(bool updateChildren, Identifiable*) const; 307 322 308 std::string typeidName_;309 323 static WeakPtr<ClassIdentifier<T> > classIdentifier_s; 310 324 }; … … 318 332 */ 319 333 template <class T> 320 inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()321 { 322 // check if the Identifier already exists323 if (!ClassIdentifier<T>::classIdentifier_s)324 ClassIdentifier<T>::initializeIdentifier(); 325 334 /*static*/ inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier() 335 { 336 if (ClassIdentifier<T>::classIdentifier_s == NULL) 337 ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*) IdentifierManager::getInstance().getIdentifierByTypeInfo(typeid(T)); 338 339 OrxVerify(ClassIdentifier<T>::classIdentifier_s != NULL, "Did you forget to register the class of type " << typeid(T).name() << "?"); 326 340 return ClassIdentifier<T>::classIdentifier_s; 327 }328 329 /**330 @brief Does the same as getIdentifier() but sets the name if this wasn't done yet.331 @param name The name of this Identifier332 @return The Identifier333 */334 template <class T>335 inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier(const std::string& name)336 {337 ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();338 identifier->setName(name);339 return identifier;340 }341 342 /**343 @brief Assigns the static field for the identifier singleton.344 */345 template <class T>346 /*static */ void ClassIdentifier<T>::initializeIdentifier()347 {348 // create a new identifier anyway. Will be deleted if not used.349 ClassIdentifier<T>* proposal = new ClassIdentifier<T>();350 351 // Get the entry from the map352 ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)IdentifierManager::getInstance().getGloballyUniqueIdentifier(proposal);353 354 if (ClassIdentifier<T>::classIdentifier_s == proposal)355 orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was not yet existing and got created." << endl;356 else357 {358 orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was already existing and got assigned." << endl;359 delete proposal; // delete proposal (it is not used anymore)360 }361 341 } 362 342 … … 375 355 IdentifierManager::getInstance().createdObject(object); 376 356 377 this->setConfigValues(object, object); 357 if (Identifier::initConfigValues_s) 358 this->setConfigValues(object, object); 359 378 360 return true; 379 361 } … … 420 402 421 403 /** 404 * @brief Destroy all objects of this class (must be Listable). 405 * Destroyables are destroyed with destroy(), all other classes with delete. 406 */ 407 template <class T> 408 void ClassIdentifier<T>::destroyObjects() 409 { 410 this->destroyObjects((T*)0); 411 } 412 413 /** 414 * @brief Only searches and destroys objects if is a @ref Listable 415 */ 416 template <class T> 417 void ClassIdentifier<T>::destroyObjects(Listable*) 418 { 419 ObjectListBase* objectList = Context::getRootContext()->getObjectList(this); 420 ObjectListElement<T>* begin = static_cast<ObjectListElement<T>*>(objectList->begin()); 421 ObjectListElement<T>* end = static_cast<ObjectListElement<T>*>(objectList->end()); 422 for (typename ObjectList<T>::iterator it = begin; it != end; ) 423 this->destroyObject(*(it++)); 424 } 425 426 template <class T> 427 void ClassIdentifier<T>::destroyObjects(void*) 428 { 429 // no action 430 } 431 432 /** 433 * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types. 434 */ 435 template <class T> 436 void ClassIdentifier<T>::destroyObject(Destroyable* object) 437 { 438 object->destroy(); 439 } 440 441 template <class T> 442 void ClassIdentifier<T>::destroyObject(void* object) 443 { 444 delete static_cast<Identifiable*>(object); 445 } 446 447 /** 422 448 @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function. 423 449 */ … … 438 464 439 465 if (updateChildren) 440 for (std::set<const Identifier*>::const_iterator it = this->getChildren Begin(); it != this->getChildrenEnd(); ++it)466 for (std::set<const Identifier*>::const_iterator it = this->getChildren().begin(); it != this->getChildren().end(); ++it) 441 467 (*it)->updateConfigValues(false); 442 468 } -
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 */ -
code/trunk/src/libraries/core/class/IdentifierManager.h
r9667 r10624 39 39 #include <map> 40 40 #include <set> 41 #include <list> 41 42 #include <string> 43 44 #include "util/Singleton.h" 42 45 43 46 namespace orxonox 44 47 { 45 class _CoreExport IdentifierManager 48 class _CoreExport IdentifierManager : public Singleton<IdentifierManager> 46 49 { 50 friend class Singleton<IdentifierManager>; 51 47 52 public: 48 static IdentifierManager& getInstance(); 53 IdentifierManager(); 54 ~IdentifierManager() {} 49 55 50 Identifier* getGloballyUniqueIdentifier(Identifier* proposal); 51 void addIdentifierToLookupMaps(Identifier* identifier); 52 53 unsigned int getUniqueClassId() 54 { return this->classIDCounter_s++; } 56 void addIdentifier(Identifier* identifier); 57 void removeIdentifier(Identifier* identifier); 55 58 56 59 … … 59 62 ///////////////////////////// 60 63 void createClassHierarchy(); 61 void destroyAllIdentifiers(); 64 void verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers); 65 void destroyClassHierarchy(); 62 66 63 67 void createdObject(Identifiable* identifiable); … … 74 78 Identifier* getIdentifierByLowercaseString(const std::string& name); 75 79 Identifier* getIdentifierByID(uint32_t id); 80 Identifier* getIdentifierByTypeInfo(const std::type_info& typeInfo); 76 81 77 82 void clearNetworkIDs(); … … 88 93 89 94 private: 90 IdentifierManager(); 91 IdentifierManager(const IdentifierManager&); 92 ~IdentifierManager() {} 95 IdentifierManager(const IdentifierManager&); // not implemented 93 96 94 97 /// Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents. … … 99 102 { hierarchyCreatingCounter_s--; } 100 103 101 std::map<std::string, Identifier*> identifierByTypeidName_; //!< Map with the names as received by typeid(). This is only used internally. 102 104 std::set<Identifier*> identifiers_; //!< All identifiers. This is only used internally. 103 105 std::map<std::string, Identifier*> identifierByString_; //!< Map that stores all Identifiers with their names. 104 106 std::map<std::string, Identifier*> identifierByLowercaseString_; //!< Map that stores all Identifiers with their names in lowercase. … … 106 108 107 109 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 109 unsigned int classIDCounter_s; //!< counter for the unique classIDs 110 111 /// Used while creating the object hierarchy to keep track of the identifiers of a newly created object (and all other objects that get created as 112 /// a consequence of this, e.g. nested member objects). 113 std::map<Identifiable*, std::list<const Identifier*> > identifierTraceOfNewObject_; 114 Identifier* recordTraceForIdentifier_; //!< The identifier for which we want to record the trace of identifiers during object creation. If null, no trace is recorded. 115 116 static IdentifierManager* singletonPtr_s; 110 117 }; 111 118 } -
code/trunk/src/libraries/core/class/OrxonoxInterface.cc
r9667 r10624 32 32 namespace orxonox 33 33 { 34 RegisterClassNoArgs(OrxonoxInterface) ;34 RegisterClassNoArgs(OrxonoxInterface).virtualBase(); 35 35 36 36 OrxonoxInterface::OrxonoxInterface() -
code/trunk/src/libraries/core/class/Super.h
r9667 r10624 274 274 SUPER_NOARGS(classname, functionname) 275 275 276 #define SUPER_changedGametype(classname, functionname, ...) \277 SUPER_NOARGS(classname, functionname)278 279 276 #define SUPER_changedUsed(classname, functionname, ...) \ 280 277 SUPER_NOARGS(classname, functionname) … … 555 552 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 556 553 557 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(9, changedGametype, false) 558 () 559 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 560 561 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(10, changedUsed, false) 562 () 563 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 564 565 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(11, changedCarrier, false) 566 () 567 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 568 569 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(12, changedPickedUp, false) 554 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(9, changedUsed, false) 555 () 556 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 557 558 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(10, changedCarrier, false) 559 () 560 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; 561 562 SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(11, changedPickedUp, false) 570 563 () 571 564 SUPER_FUNCTION_GLOBAL_DECLARATION_PART2; … … 623 616 SUPER_INTRUSIVE_DECLARATION(changedOverlayGroup); 624 617 SUPER_INTRUSIVE_DECLARATION(changedName); 625 SUPER_INTRUSIVE_DECLARATION(changedGametype);626 618 SUPER_INTRUSIVE_DECLARATION(changedUsed); 627 619 SUPER_INTRUSIVE_DECLARATION(changedCarrier);
Note: See TracChangeset
for help on using the changeset viewer.