![]() |
|
|||
File indexing completed on 2025-02-21 10:00:33
0001 /***********************************************************************************\ 0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations * 0003 * * 0004 * This software is distributed under the terms of the Apache version 2 licence, * 0005 * copied verbatim in the file "LICENSE". * 0006 * * 0007 * In applying this licence, CERN does not waive the privileges and immunities * 0008 * granted to it by virtue of its status as an Intergovernmental Organization * 0009 * or submit itself to any jurisdiction. * 0010 \***********************************************************************************/ 0011 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H 0012 #define GAUDIKERNEL_KEYEDCONTAINER_H 0013 0014 // Include files 0015 #include <algorithm> 0016 #include <iterator> 0017 0018 namespace GaudiDict { 0019 template <class T> 0020 struct KeyedContainerDict; 0021 } 0022 0023 // Framework include files 0024 #include "GaudiKernel/KeyedObject.h" 0025 #include "GaudiKernel/KeyedObjectManager.h" 0026 #include "GaudiKernel/ObjectContainerBase.h" 0027 0028 // Forward declarations 0029 // template <class T, class M> class KeyedContainer; 0030 0031 #ifdef WIN32 0032 # define FORCE_INLINE __forceinline 0033 #else 0034 # define FORCE_INLINE inline 0035 #endif 0036 0037 /** template class KeyedContainer, KeyedContainer.h 0038 * 0039 * This class represents a container, where the contained objects 0040 * are accessed by a key. Such a key can be any class, which is able 0041 * to convert to and from a 32-bit (long) integer. 0042 * 0043 * To insert objects into the container, this implementation 0044 * determines the key in the following way: 0045 * - If the object is already keyed, the object's key is kept 0046 * and cannot be modified. 0047 * - If the object is NOT keyed, and a key is supplied, 0048 * this key is used to register the object in the map and 0049 * the same key is given to the object. 0050 * - If the object is NOT keyed, and NO key is supplied, 0051 * a key is generated by the map implementation and this 0052 * key is given to the object. 0053 * 0054 * - It is not possible to insert two objects with the same key 0055 * into the same container. This causes an exception. 0056 * 0057 * Access to objects is given two-fold: 0058 * - Using iterators. This access is very efficient. The container 0059 * however, may not be manipulated: No objects may not be 0060 * inserted or removed using iterators. 0061 * - Using object keys: This access patterns provides random 0062 * access to objects. 0063 * 0064 * The KeyedContainer class uses for further specialization a traits 0065 * class. By specializing these traits extra behaviour can be 0066 * forced on request for special containers or special keys. 0067 * 0068 * 0069 * @author M.Frank CERN/LHCb 0070 * @version 1.0 0071 * 0072 */ 0073 template <class DATATYPE, class MAPPING = Containers::HashMap> 0074 class GAUDI_API KeyedContainer : public ObjectContainerBase { 0075 friend struct GaudiDict::KeyedContainerDict<DATATYPE>; 0076 0077 public: 0078 /// Definition of the contained object type 0079 typedef DATATYPE contained_type; 0080 /// Definition of the implementing container type 0081 typedef MAPPING container_type; 0082 0083 /** General container specific type definitions. 0084 The following type definitions are generic to most STL containers 0085 and are also presented by the KeyedContainer class. 0086 These forward declarations typically are used by STL algorithms. 0087 */ 0088 //@{ 0089 /// Definition of the STL sequential access type 0090 typedef typename std::vector<contained_type*> seq_type; 0091 /// Definition of the key type: re-use definition of contained type 0092 typedef typename contained_type::key_type key_type; 0093 /// Sequential access: definition of type stored in sequential container 0094 typedef typename seq_type::value_type value_type; 0095 /// Sequential access: reference type used in sequential container 0096 typedef typename seq_type::reference reference; 0097 /// Sequential access: const reference type used in sequential container 0098 typedef typename seq_type::const_reference const_reference; 0099 /// Sequential access: iterator type used in sequential container 0100 typedef typename seq_type::iterator iterator; 0101 /// Sequential access: const iterator type used in sequential container 0102 typedef typename seq_type::const_iterator const_iterator; 0103 /// Sequential access: reverse iterator type used in sequential container 0104 typedef typename seq_type::reverse_iterator reverse_iterator; 0105 /** Sequential access: const reverse iterator type used in 0106 sequential container. 0107 */ 0108 typedef typename seq_type::const_reverse_iterator const_reverse_iterator; 0109 //@} 0110 private: 0111 /** Traits class definition. Specializing traits allows to specialize the 0112 * container implementation for special needs. 0113 */ 0114 typedef typename Containers::traits<container_type, contained_type> traits; 0115 0116 /**@name Implementation helpers. 0117 */ 0118 //@{ 0119 /// Map container to facilitate object access by key. 0120 container_type m_cont; 0121 /// Array to allow sequential access to the object (can be ordered). 0122 seq_type m_sequential; 0123 /// Array to allow random access to objects (not exposed) 0124 seq_type* m_random; 0125 0126 /// Internal function to access objects within the container 0127 #ifdef CHECK_KEYED_CONTAINER 0128 value_type i_object( const key_type& k ) const { 0129 if ( 0 == m_cont.isDirect() ) { 0130 if ( traits::checkBounds( m_random, k ) ) { 0131 value_type p = *( m_random->begin() + traits::hash( k ) ); 0132 if ( traits::checkKey( p, k ) ) { return p; } 0133 } 0134 return 0; 0135 } 0136 value_type p = value_type( m_cont.object( traits::hash( k ) ) ); 0137 return traits::checkKey( p, k ) ? p : 0; 0138 } 0139 #else 0140 FORCE_INLINE value_type i_object( const key_type& k ) const { 0141 return 0 == m_cont.isDirect() ? value_type( *( m_random->begin() + traits::hash( k ) ) ) 0142 : value_type( m_cont.object( traits::hash( k ) ) ); 0143 } 0144 #endif 0145 /// Internal function to erase an object from the container 0146 long i_erase( const_reference v, const key_type& k ) { 0147 value_type p = value_type( m_cont.erase( traits::hash( k ), v ) ); 0148 if ( p ) { 0149 if ( p->parent() == this ) { p->setParent( 0 ); } 0150 } 0151 return traits::release( p ) <= 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_DELETED; 0152 } 0153 0154 /// Internal functor for insertion of objects 0155 struct _InsertRelease { 0156 KeyedContainer<DATATYPE, MAPPING>* m_obj; 0157 _InsertRelease( KeyedContainer<DATATYPE, MAPPING>* p ) : m_obj( p ) {} 0158 void operator()( value_type p ) { 0159 m_obj->insert( p ); 0160 traits::release( p ); 0161 } 0162 }; 0163 0164 /// Internal functor for insertion of objects 0165 struct _RemoveRelease { 0166 ObjectContainerBase* m_obj; 0167 _RemoveRelease( ObjectContainerBase* p ) : m_obj( p ) {} 0168 void operator()( value_type p ) { 0169 const ObjectContainerBase* par = p->parent(); 0170 if ( par == m_obj ) { p->setParent( 0 ); } 0171 traits::release( p ); 0172 } 0173 }; 0174 //@} 0175 0176 public: 0177 /**@name Constructors/Destructors 0178 */ 0179 //@{ 0180 /// Standard Constructor 0181 KeyedContainer( void ) { 0182 // avoid problems with strict-aliasing rules 0183 seq_type** rptr = &m_random; 0184 seq_type* sptr = &m_sequential; 0185 m_cont.setup( (void*)sptr, (void**)rptr ); 0186 } 0187 KeyedContainer( KeyedContainer&& other ) 0188 : ObjectContainerBase( std::move( other ) ) 0189 , m_cont( std::move( other.m_cont ) ) 0190 , m_sequential( std::move( other.m_sequential ) ) { 0191 m_cont.setup( (void*)&m_sequential, (void**)&m_random ); 0192 std::for_each( begin(), end(), [this]( ContainedObject* obj ) { obj->setParent( this ); } ); 0193 0194 other.m_cont.setup( (void*)&other.m_sequential, (void**)&other.m_random ); 0195 } 0196 KeyedContainer( const KeyedContainer& ) = delete; 0197 /// Destructor 0198 ~KeyedContainer() override; 0199 //@} 0200 0201 /**@name DataObject virtual function overloads. 0202 * The implementation of these methods is required by the DataObject 0203 * base class and determines the persistent run-time-type information. 0204 */ 0205 //@{ 0206 /// Retrieve class ID 0207 const CLID& clID() const override { return this->classID(); } 0208 /// Retrieve class ID 0209 static const CLID& classID() { 0210 static CLID clid = contained_type::classID() + container_type::classID(); 0211 return clid; 0212 } 0213 //@} 0214 0215 /**@name NOT FOR GENERAL USE ObjectContainerBase function overloads. 0216 * 0217 * The implementation of these methods ensure the behaviour 0218 * of the class as a type of class ObjectContainerBase. This 0219 * base class and its behaviour are only used by "generic" 0220 * object handlers. These classes collaborate with several 0221 * classes such as the 0222 * 0223 * - SmartRef classes. 0224 * - Generic converters. 0225 * - Interfaces for interactivity (e.g. Python) 0226 * 0227 * For this reason, the entry points in this section are reserved 0228 * for "generic" object handling and should NOT be used in public. 0229 */ 0230 //@{ 0231 /// ObjectContainerBase overload: Number of objects in the container 0232 size_type numberOfObjects() const override { return m_sequential.size(); } 0233 /** ObjectContainerBase overload: Add an object to the container. 0234 * Plese see the documentation of the member function 0235 * 0236 * const key_type& insert(DATATYPE* pObject) 0237 * 0238 * for further details. 0239 * 0240 * @param pObject Pointer to the object to be inserted into the 0241 * container. 0242 * @return long integer representation of the key value. 0243 */ 0244 long add( ContainedObject* pObject ) override; 0245 0246 /** ObjectContainerBase overload: Remove an object from the container. 0247 * Because this function is also called from the destructor of 0248 * The ContainedObject class, it is no longer possible to deduce 0249 * the key from the object itself. It is hence necessary to relay 0250 * on the **NON-EXISTENCE** of virtual inheritance, ie. 0251 * (void*)pObject = (void*)(contained_object). 0252 * If the virtual object table is still intact, the normal erase 0253 * is called. 0254 * 0255 * @param pObject Pointer to the object to be removed from the 0256 * container. 0257 */ 0258 long remove( ContainedObject* pObject ) override; 0259 0260 /** ObjectContainerBase overload: Retrieve the object by reference 0261 * given the long integer representation of the object's key. 0262 */ 0263 ContainedObject* containedObject( long key_value ) override { return i_object( traits::makeKey( key_value ) ); } 0264 ContainedObject const* containedObject( long key_value ) const override { 0265 return i_object( traits::makeKey( key_value ) ); 0266 } 0267 /** ObjectContainerBase overload: Retrieve the full long integer 0268 * representation of the object's key from the object base class pointer. 0269 */ 0270 long index( const ContainedObject* p ) const override; 0271 /** Retrieve the full content of the object container. 0272 * @param v Vector of contained objects, which will host 0273 * all objects contained in this container. 0274 * @return Number of objects returned in v. 0275 */ 0276 virtual size_type containedObjects( std::vector<ContainedObject*>& v ) const; 0277 //@} 0278 0279 /**@name Container related implementation. 0280 * These methods allow to manipulate the container as a whole and to 0281 * retrieve information about the internal behaviour of the container. 0282 */ 0283 //@{ 0284 /// Number of objects in the container 0285 size_type size() const { return m_sequential.size(); } 0286 /// For consistency with STL: check if container is empty 0287 bool empty() const { return m_sequential.empty(); } 0288 /// Reserve place for "value" objects in the container. 0289 void reserve( size_type value ) { m_cont.reserve( value ); } 0290 /// Clear the entire content and erase the objects from the container 0291 void clear() { erase( begin(), end() ); } 0292 /** Retrieve the full content of the object container by reference. 0293 * Returned is the random access container if in sequntial direct 0294 * access mode. Otherwise the sequential access container is returned 0295 * @return Reference to sequencal access container. 0296 */ 0297 virtual const std::vector<const ContainedObject*>* containedObjects() const; 0298 /** Reconfigure direct access to elements (Needed by POOL data loading) 0299 * This function reuses the "update" callback of the generic DataObject 0300 * base class. 0301 */ 0302 StatusCode update() override; 0303 //@} 0304 0305 /**@name Sequential array access to objects using iterators. 0306 * 0307 * Sequential object access using iterators is much faster then object 0308 * access by key. In case all objects of the container should be 0309 * addressed, use iterators rather than direct object access. 0310 * 0311 * - If the container is accessed through the iterators defined below, 0312 * the elements may be sorted according to the user needs. 0313 * - The container can be accesses in both const and non-const mode. 0314 * - Iterations are supported in both directions: From the beginning to 0315 * the end and the reverse. 0316 */ 0317 //@{ 0318 /// Retrieve start iterator 0319 iterator begin() { return m_sequential.begin(); } 0320 /// Retrieve start const iterator 0321 const_iterator begin() const { return m_sequential.begin(); } 0322 /// Retrieve terminating iterator 0323 iterator end() { return m_sequential.end(); } 0324 /// Retrieve terminating const iterator 0325 const_iterator end() const { return m_sequential.end(); } 0326 /// reverse_iterator returns the beginning of the reversed container 0327 reverse_iterator rbegin() { return m_sequential.rbegin(); } 0328 /// const reverse_iterator returns the beginning of the reversed container 0329 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); } 0330 /// reverse_iterator pointing to the end of the reversed container 0331 reverse_iterator rend() { return m_sequential.rend(); } 0332 /// const reverse_iterator pointing to the end of the reversed container 0333 const_reverse_iterator rend() const { return m_sequential.rend(); } 0334 //@} 0335 0336 /**@name Random access to objects in the container. 0337 * Access to objects is given by Key. 0338 * Please note, that random object access is nearly in all cases 0339 * significantly slower than sequential access. If all objects 0340 * in the contaienr should be addresses sequentially, use iterators 0341 * rather than direct access. Direct access should only be used 0342 * for selective retrieval of objects. 0343 */ 0344 //@{ 0345 /** Object access by key. 0346 * Access contained objects by key. 0347 * 0348 * @param kval Key of the object to be returned. 0349 * @return Valid reference to the requested object. If the key of the 0350 * requested object cannot be found in the container a null 0351 * reference is returned. 0352 */ 0353 value_type object( const key_type& kval ) const { return i_object( kval ); } 0354 0355 /** STL algorithms support for object access. 0356 * Access contained objects by key using the operator(), which is demanded 0357 * by STL algorithms. 0358 * 0359 * @param kval Key of the object to be returned. 0360 * @return Valid reference to the requested object. If the key of the 0361 * requested object cannot be found in the container a null 0362 * reference is returned. 0363 */ 0364 value_type operator()( const key_type& kval ) const { return i_object( kval ); } 0365 //@} 0366 0367 /**@name Insert/Remove objects from the container. 0368 * Objects generally are identified by key. Since keys are stored with 0369 * the objects, insertions and removals are possible by key or by 0370 * reference. 0371 */ 0372 //@{ 0373 /** Remove/erase object (identified by key) from the container. 0374 * 0375 * @param kval Key to identify the object within the container. 0376 * @return Enumeration value from the Containers namespace: 0377 * - OBJ_NOT_FOUND: The indicated object was not found 0378 * in the container 0379 * - OBJ_ERASED: The indicated object was found 0380 * and removed from the container. 0381 * The object was not yet deleted, 0382 * because its reference count was 0383 * non zero. 0384 * - OBJ_DELETED The indicated object was found 0385 * and removed from the container. 0386 * The object was deleted, because 0387 * its reference count was zero. 0388 */ 0389 long erase( const key_type& kval ) { return i_erase( 0, kval ); } 0390 0391 /** Remove/erase object (identified by pointer value) from the container. 0392 * This member function removes an object, which is identified by its 0393 * reference from the container. No key value is supplied. To identify 0394 * the object within the container, the key of the object is used as 0395 * it can be retrieved using the KeyedObject::key() method. 0396 * 0397 * @param val Reference to object to be removed from the container. 0398 * @return Enumeration value from the Containers namespace: 0399 * - OBJ_NOT_FOUND: The indicated object was not found 0400 * in the container 0401 * - OBJ_ERASED: The indicated object was found 0402 * and removed from the container. 0403 * The object was not yet deleted, 0404 * because its reference count was 0405 * non zero. 0406 * - OBJ_DELETED The indicated object was found 0407 * and removed from the container. 0408 * The object was deleted, because 0409 * its reference count was zero. 0410 */ 0411 long erase( const value_type val ) { return ( val ) ? i_erase( val, val->key() ) : (long)Containers::OBJ_NOT_FOUND; } 0412 0413 /** Remove/erase object (identified by iterator) from the container. 0414 * This member function removes an object, which is identified by its 0415 * reference from the container. No key value is supplied. To identify 0416 * the object within the container, the key of the object is used as 0417 * it can be retrieved using the KeyedObject::key() method. 0418 * 0419 * @param val Reference to object to be removed from the container. 0420 * @return Enumeration value from the Containers namespace: 0421 * - OBJ_NOT_FOUND: The indicated object was not found 0422 * in the container 0423 * - OBJ_ERASED: The indicated object was found 0424 * and removed from the container. 0425 * The object was not yet deleted, 0426 * because its reference count was 0427 * non zero. 0428 * - OBJ_DELETED The indicated object was found 0429 * and removed from the container. 0430 * The object was deleted, because 0431 * its reference count was zero. 0432 */ 0433 long erase( iterator pos ) { return erase( *pos ); } 0434 0435 /** Remove/erase objects by iterator range. 0436 * This member function removes all objects, which are within 0437 * the sequential iterator range [pos_start, pos_stop[. 0438 * 0439 * @param pos_start Starting iterator of the range to be removed. 0440 * @param pos_stop Starting iterator of the range to be removed. 0441 * @param use_temp Flag to indicate that a temporary arry should be used. 0442 */ 0443 void erase( iterator pos_start, iterator pos_stop, bool use_temp = false ); 0444 0445 /** Insert entry to the container with a valid key. 0446 * This member function inserts an element, which is identified by its 0447 * reference to the container. The element will be inserted using the 0448 * specified key. If the object is already keyed, the long 0449 * representations of the supplied key and the object's key must agree. 0450 * 0451 * The object will not be inserted and an exception will be raised 0452 * under the following conditions: 0453 * - The supplied key does not agree with the object's key. 0454 * - An object with the supplied key is already present in the container. 0455 * 0456 * @param val Reference to object to be inserted into the container. 0457 * The object reference may NOT be NULL. 0458 * @param kval Key to identify the object within the container. 0459 * @return Key, which was used to index the object within the 0460 * container. If the operation is not 0461 * successful, an exception is thrown. 0462 */ 0463 const key_type& insert( const value_type val, const key_type& kval ); 0464 0465 /** Insert entry to the container with automatic key assignment. 0466 * This member function inserts an element, which is identified by its 0467 * reference to the container. No key value is supplied. The key 0468 * used to insert the object is retrieved from the element itself. 0469 * In the event the object already has a key, the assigned key of 0470 * the object is used. If no key was assigned to the object, 0471 * (i.e. the object's key is equal to the invalid key), 0472 * a key is generated according to the number of objects present in 0473 * the container. 0474 * 0475 * The object will not be inserted and an exception will be raised 0476 * under the following conditions: 0477 * - A key was already assigned to the object, but 0478 * another object with the same key is already present 0479 * in the container. 0480 * 0481 * @param val Reference to object to be inserted into the container. 0482 * @return Key, which was used to index the object within the 0483 * container. If the operation is not 0484 * successful, an exception is thrown. 0485 */ 0486 const key_type& insert( const value_type val ); 0487 //@} 0488 }; 0489 0490 /** 0491 * 0492 * 0493 * Inline code for keyed container class 0494 * 0495 */ 0496 0497 // Destructor 0498 template <class DATATYPE, class MAPPING> 0499 inline KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer() { 0500 clear(); 0501 m_cont.clear(); 0502 } 0503 0504 // Configure direct access 0505 template <class DATATYPE, class MAPPING> 0506 inline StatusCode KeyedContainer<DATATYPE, MAPPING>::update() { 0507 int count = 0; 0508 m_cont.clearDirect(); 0509 typename seq_type::iterator i = m_sequential.begin(); 0510 typename seq_type::iterator s = m_sequential.end(); 0511 for ( ; i != s; i++ ) { 0512 typename seq_type::value_type v = *i; 0513 if ( v ) { 0514 if ( !v->hasKey() ) { 0515 traits::setKey( v, v->key() ); 0516 traits::addRef( v ); 0517 } 0518 long k0 = traits::hash( v->key() ); 0519 if ( m_cont.insertDirect( this, v, v, k0 ) == Containers::OBJ_INSERTED ) {} 0520 } else { 0521 ++count; 0522 } 0523 } 0524 if ( count > 0 ) { Containers::cannotInsertToContainer(); } 0525 return StatusCode::SUCCESS; 0526 } 0527 0528 // Retrieve the full content of the object container by reference. 0529 template <class DATATYPE, class MAPPING> 0530 inline const std::vector<const ContainedObject*>* KeyedContainer<DATATYPE, MAPPING>::containedObjects() const { 0531 return (const std::vector<const ContainedObject*>*)( ( 0 == m_cont.isDirect() ) ? m_random : &m_sequential ); 0532 } 0533 0534 template <class DATATYPE, class MAPPING> 0535 inline const typename KeyedContainer<DATATYPE, MAPPING>::key_type& 0536 KeyedContainer<DATATYPE, MAPPING>::insert( const value_type val, const key_type& kval ) { 0537 if ( val ) { 0538 long k0 = traits::hash( kval ); 0539 if ( !val->hasKey() || ( traits::hash( val->key() ) == k0 ) ) { 0540 if ( m_cont.insert( this, val, val, k0 ) == Containers::OBJ_INSERTED ) { 0541 if ( !val->hasKey() ) traits::setKey( val, kval ); 0542 traits::addRef( val ); 0543 return val->key(); 0544 } 0545 } 0546 } 0547 // Cannot insert object...indicate bad object insertion... 0548 Containers::cannotInsertToContainer(); 0549 return val->key(); 0550 } 0551 0552 // Insert object 0553 template <class DATATYPE, class MAPPING> // inline 0554 const typename KeyedContainer<DATATYPE, MAPPING>::key_type& 0555 KeyedContainer<DATATYPE, MAPPING>::insert( const value_type val ) { 0556 if ( 0 != val ) { 0557 if ( val->hasKey() ) { 0558 if ( m_cont.insert( this, val, val, traits::hash( val->key() ) ) == Containers::OBJ_INSERTED ) { 0559 traits::addRef( val ); 0560 return val->key(); 0561 } 0562 } 0563 long k0; 0564 if ( m_cont.insert( this, val, val, &k0 ) == Containers::OBJ_INSERTED ) { 0565 traits::setKey( val, traits::makeKey( k0 ) ); 0566 traits::addRef( val ); 0567 return val->key(); 0568 } 0569 } 0570 // Cannot insert object...indicate bad object insertion... 0571 Containers::cannotInsertToContainer(); 0572 return val->key(); 0573 } 0574 0575 template <class DATATYPE, class MAPPING> 0576 inline long KeyedContainer<DATATYPE, MAPPING>::index( const ContainedObject* p ) const { 0577 const contained_type* ptr = dynamic_cast<const contained_type*>( p ); 0578 if ( ptr ) return traits::identifier( ptr->key() ); 0579 return -1; 0580 } 0581 0582 // Retrieve the full content of the object container. 0583 template <class DATATYPE, class MAPPING> 0584 inline typename KeyedContainer<DATATYPE, MAPPING>::size_type 0585 KeyedContainer<DATATYPE, MAPPING>::containedObjects( std::vector<ContainedObject*>& vec ) const { 0586 typename seq_type::const_iterator i = m_sequential.begin(); 0587 typename seq_type::const_iterator s = m_sequential.end(); 0588 vec.clear(); 0589 vec.reserve( size() ); 0590 for ( ; i != s; i++ ) { 0591 ContainedObject* p = const_cast<typename seq_type::value_type>( *i ); 0592 vec.push_back( p ); 0593 } 0594 return vec.size(); 0595 } 0596 0597 // ObjectContainerBase overload: Add an object to the container. 0598 template <class DATATYPE, class MAPPING> 0599 inline long KeyedContainer<DATATYPE, MAPPING>::add( ContainedObject* pObject ) { 0600 return traits::identifier( insert( dynamic_cast<typename seq_type::value_type>( pObject ) ) ); 0601 } 0602 0603 // ObjectContainerBase overload: Remove an object from the container. 0604 template <class DATATYPE, class MAPPING> 0605 inline long KeyedContainer<DATATYPE, MAPPING>::remove( ContainedObject* p ) { 0606 contained_type* p1 = dynamic_cast<contained_type*>( p ); 0607 if ( p1 ) { // Normal case; object still fully intact 0608 return this->erase( p1 ); 0609 } else if ( p ) { 0610 const ObjectContainerBase* par = p->parent(); 0611 // The following should never occur: object is in a funny state, 0612 // Because the parent was explicitly set to NULL in the 0613 // KeyeObject destructor. 0614 // - It cannot be a KeyedObject: It would not have a parent 0615 // - Still the parent is present: We are not in the destructor 0616 // of KeyedObject 0617 if ( par ) { Containers::invalidContainerOperation(); } 0618 return m_cont.erase( 0, p ) == 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_NOT_FOUND; 0619 } 0620 return (long)Containers::OBJ_NOT_FOUND; 0621 } 0622 0623 template <class DATATYPE, class MAPPING> 0624 inline void KeyedContainer<DATATYPE, MAPPING>::erase( iterator start_pos, iterator stop_pos, bool use_tmp ) { 0625 bool is_start = start_pos == m_sequential.begin(); 0626 bool is_stop = stop_pos == m_sequential.end(); 0627 if ( is_start && is_stop ) { 0628 // Nothing special. Taken care of by Keyed object manager 0629 } else if ( is_start || is_stop || use_tmp ) { 0630 std::vector<DATATYPE*> tmp( m_sequential.begin(), start_pos ); 0631 tmp.insert( tmp.end(), stop_pos, m_sequential.end() ); 0632 std::for_each( tmp.begin(), tmp.end(), traits::addRef ); 0633 this->erase( m_sequential.begin(), m_sequential.end() ); 0634 std::for_each( tmp.begin(), tmp.end(), _InsertRelease( this ) ); 0635 return; 0636 } 0637 std::for_each( start_pos, stop_pos, _RemoveRelease( this ) ); 0638 seq_type* sptr = &m_sequential; // avoid problems with strict-aliasing rules 0639 std::vector<void*>* v = (std::vector<void*>*)sptr; 0640 std::vector<void*>::iterator i1 = v->begin() + std::distance( m_sequential.begin(), start_pos ); 0641 std::vector<void*>::iterator i2 = v->begin() + std::distance( m_sequential.begin(), stop_pos ); 0642 m_cont.erase( i1, i2 ); 0643 } 0644 0645 #undef FORCE_INLINE 0646 #endif // GAUDIKERNEL_KEYEDCONTAINER_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |