![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Id $ 00002 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H 00003 #define GAUDIKERNEL_KEYEDCONTAINER_H 00004 00005 // Include files 00006 #include <iterator> 00007 #include <algorithm> 00008 00009 namespace GaudiDict { 00010 template <class T> struct KeyedContainerDict; 00011 } 00012 00013 // Framework include files 00014 #include "GaudiKernel/ObjectContainerBase.h" 00015 #include "GaudiKernel/KeyedObjectManager.h" 00016 #include "GaudiKernel/KeyedObject.h" 00017 00018 // Forward declarations 00019 // template <class T, class M> class KeyedContainer; 00020 00021 #ifdef WIN32 00022 #define FORCE_INLINE __forceinline 00023 #else 00024 #define FORCE_INLINE inline 00025 #endif 00026 00063 template <class DATATYPE, class MAPPING=Containers::HashMap > 00064 class KeyedContainer 00065 : public ObjectContainerBase 00066 { 00067 friend struct GaudiDict::KeyedContainerDict<DATATYPE>; 00068 00069 public: 00071 typedef DATATYPE contained_type; 00073 typedef MAPPING container_type; 00074 00081 00082 typedef typename std::vector<contained_type*> seq_type; 00084 typedef typename contained_type::key_type key_type; 00086 typedef typename seq_type::value_type value_type; 00088 typedef typename seq_type::reference reference; 00090 typedef typename seq_type::const_reference const_reference; 00092 typedef typename seq_type::iterator iterator; 00094 typedef typename seq_type::const_iterator const_iterator; 00096 typedef typename seq_type::reverse_iterator reverse_iterator; 00100 typedef typename seq_type::const_reverse_iterator const_reverse_iterator; 00102 private: 00106 typedef typename Containers::traits<container_type, contained_type> traits; 00107 00111 00112 container_type m_cont; 00114 seq_type m_sequential; 00116 seq_type* m_random; 00117 00119 #ifdef CHECK_KEYED_CONTAINER 00120 value_type i_object(const key_type& k) const { 00121 if ( 0 == m_cont.isDirect() ) { 00122 if ( traits::checkBounds(m_random, k) ) { 00123 value_type p = *(m_random->begin()+traits::hash(k)); 00124 if ( traits::checkKey(p, k) ) { 00125 return p; 00126 } 00127 } 00128 return 0; 00129 } 00130 value_type p = value_type(m_cont.object(traits::hash(k))); 00131 return traits::checkKey(p, k) ? p : 0; 00132 } 00133 #else 00134 FORCE_INLINE value_type i_object(const key_type& k) const { 00135 return 0==m_cont.isDirect() 00136 ? value_type(*(m_random->begin()+traits::hash(k))) 00137 : value_type(m_cont.object(traits::hash(k))); 00138 } 00139 #endif 00141 long i_erase(const_reference v, const key_type& k) { 00142 value_type p = value_type(m_cont.erase(traits::hash(k), v)); 00143 if ( p ) { 00144 if ( p->parent() == this ) { 00145 p->setParent(0); 00146 } 00147 } 00148 return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED 00149 : (long) Containers::OBJ_DELETED; 00150 } 00151 00153 struct _InsertRelease { 00154 KeyedContainer<DATATYPE,MAPPING>* m_obj; 00155 _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {} 00156 void operator()(value_type p) { 00157 m_obj->insert(p); 00158 traits::release(p); 00159 } 00160 }; 00161 00163 struct _RemoveRelease { 00164 ObjectContainerBase* m_obj; 00165 _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {} 00166 void operator()(value_type p) { 00167 const ObjectContainerBase* par = p->parent(); 00168 if ( par == m_obj ) { 00169 p->setParent(0); 00170 } 00171 traits::release(p); 00172 } 00173 }; 00175 00176 public: 00180 00181 KeyedContainer(void) 00182 { 00183 // avoid problems with strict-aliasing rules 00184 seq_type** rptr = &m_random; 00185 seq_type* sptr = &m_sequential; 00186 m_cont.setup((void*)sptr,(void**)rptr); 00187 } 00189 virtual ~KeyedContainer(); 00191 00197 00198 virtual const CLID& clID() const { return this->classID(); } 00200 static const CLID& classID() { 00201 static CLID clid = contained_type::classID() + container_type::classID(); 00202 return clid; 00203 } 00205 00222 00223 virtual long numberOfObjects() const { return m_sequential.size(); } 00235 virtual long add(ContainedObject* pObject); 00236 00249 virtual long remove(ContainedObject* pObject); 00250 00254 virtual ContainedObject* containedObject(long key_value) const { 00255 return i_object( traits::makeKey( key_value ) ); 00256 } 00260 virtual long index(const ContainedObject* p) const; 00266 virtual long containedObjects(std::vector<ContainedObject*>& v) const; 00268 00274 00275 long size() const { return m_sequential.size(); } 00277 bool empty() const { return m_sequential.empty(); } 00279 void reserve(long value) { m_cont.reserve(value); } 00281 void clear() { erase(begin(), end()); } 00287 virtual const std::vector<const ContainedObject*>* containedObjects() const; 00289 virtual void configureDirectAccess(); 00291 00305 00306 iterator begin() { return m_sequential.begin(); } 00308 const_iterator begin() const { return m_sequential.begin(); } 00310 iterator end() { return m_sequential.end(); } 00312 const_iterator end() const { return m_sequential.end(); } 00314 reverse_iterator rbegin() { return m_sequential.rbegin(); } 00316 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); } 00318 reverse_iterator rend() { return m_sequential.rend(); } 00320 const_reverse_iterator rend() const { return m_sequential.rend(); } 00322 00340 value_type object(const key_type& kval) const { return i_object(kval); } 00341 00351 value_type operator()(const key_type& kval) const { return i_object(kval); } 00353 00376 long erase(const key_type& kval) { return i_erase(0, kval); } 00377 00398 long erase(const value_type val) { 00399 return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND; 00400 } 00401 00422 long erase(iterator pos) { return erase(*pos); } 00423 00432 void erase(iterator pos_start, iterator pos_stop, bool use_temp=false); 00433 00452 const key_type& insert(const value_type val, const key_type& kval); 00453 00475 const key_type& insert(const value_type val); 00477 }; 00478 00479 00487 // Destructor 00488 template <class DATATYPE, class MAPPING> inline 00489 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer() 00490 { 00491 erase(begin(), end()); 00492 m_cont.clear(); 00493 } 00494 00495 // Configure direct access 00496 template <class DATATYPE, class MAPPING> inline 00497 void KeyedContainer<DATATYPE, MAPPING>::configureDirectAccess() 00498 { 00499 int count = 0; 00500 m_cont.clearDirect(); 00501 typename seq_type::iterator i = m_sequential.begin(); 00502 typename seq_type::iterator s = m_sequential.end(); 00503 for ( ; i != s; i++ ) { 00504 typename seq_type::value_type v = *i; 00505 if ( v ) { 00506 if ( !v->hasKey() ) { 00507 traits::setKey(v, v->key()); 00508 traits::addRef(v); 00509 } 00510 long k0 = traits::hash(v->key()); 00511 if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) { 00512 } 00513 } 00514 else { 00515 ++count; 00516 } 00517 } 00518 if ( count > 0 ) { 00519 Containers::cannotInsertToContainer(); 00520 } 00521 } 00522 00523 00524 // Retrieve the full content of the object container by reference. 00525 template <class DATATYPE, class MAPPING> inline 00526 const std::vector<const ContainedObject*>* 00527 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const { 00528 return (const std::vector<const ContainedObject*>*) 00529 ((0==m_cont.isDirect()) ? m_random : &m_sequential); 00530 } 00531 00532 template <class DATATYPE, class MAPPING> inline 00533 const typename KeyedContainer<DATATYPE, MAPPING>::key_type& 00534 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val, 00535 const key_type& kval) 00536 { 00537 if ( val ) { 00538 long k0 = traits::hash(kval); 00539 if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) { 00540 if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) { 00541 if ( !val->hasKey() ) traits::setKey(val, kval); 00542 traits::addRef(val); 00543 return val->key(); 00544 } 00545 } 00546 } 00547 // Cannot insert object...indicate bad object insertion... 00548 Containers::cannotInsertToContainer(); 00549 return val->key(); 00550 } 00551 00552 // Insert object 00553 template <class DATATYPE, class MAPPING> //inline 00554 const typename KeyedContainer<DATATYPE, MAPPING>::key_type& 00555 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val) 00556 { 00557 if ( 0 != val ) { 00558 if ( val->hasKey() ) { 00559 if (m_cont.insert(this,val,val,traits::hash(val->key())) 00560 == Containers::OBJ_INSERTED) { 00561 traits::addRef(val); 00562 return val->key(); 00563 } 00564 } 00565 long k0; 00566 if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) { 00567 traits::setKey(val, traits::makeKey(k0)); 00568 traits::addRef(val); 00569 return val->key(); 00570 } 00571 } 00572 // Cannot insert object...indicate bad object insertion... 00573 Containers::cannotInsertToContainer(); 00574 return val->key(); 00575 } 00576 00577 template <class DATATYPE, class MAPPING> inline 00578 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const 00579 { 00580 const contained_type* ptr = dynamic_cast<const contained_type*>(p); 00581 if ( ptr ) return traits::identifier(ptr->key()); 00582 return -1; 00583 } 00584 00585 // Retrieve the full content of the object container. 00586 template <class DATATYPE, class MAPPING> inline 00587 long KeyedContainer<DATATYPE, MAPPING>::containedObjects 00588 (std::vector<ContainedObject*>& vec) const 00589 { 00590 typename seq_type::const_iterator i = m_sequential.begin(); 00591 typename seq_type::const_iterator s = m_sequential.end(); 00592 vec.clear(); 00593 vec.reserve(size()); 00594 for ( ; i != s; i++ ) { 00595 ContainedObject* p = const_cast<typename seq_type::value_type>(*i); 00596 vec.push_back(p); 00597 } 00598 return vec.size(); 00599 } 00600 00601 // ObjectContainerBase overload: Add an object to the container. 00602 template <class DATATYPE, class MAPPING> inline 00603 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject) 00604 { 00605 return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject))); 00606 } 00607 00608 // ObjectContainerBase overload: Remove an object from the container. 00609 template <class DATATYPE, class MAPPING> inline 00610 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p) 00611 { 00612 contained_type* p1 = dynamic_cast<contained_type*>(p); 00613 if ( p1 ) { // Normal case; object still fully intact 00614 return this->erase(p1); 00615 } 00616 else if ( p ) { 00617 const ObjectContainerBase* par = p->parent(); 00618 // The following should never occur: object is in a funny state, 00619 // Because the parent was explicitly set to NULL in the 00620 // KeyeObject destructor. 00621 // - It cannot be a KeyedObject: It would not have a parent 00622 // - Still the parent is present: We are not in the destructor 00623 // of KeyedObject 00624 if ( par ) { 00625 Containers::invalidContainerOperation(); 00626 } 00627 return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED 00628 : (long) Containers::OBJ_NOT_FOUND; 00629 } 00630 return (long) Containers::OBJ_NOT_FOUND; 00631 } 00632 00633 template <class DATATYPE, class MAPPING> inline 00634 void 00635 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos, 00636 iterator stop_pos, 00637 bool use_tmp) 00638 { 00639 bool is_start = start_pos == m_sequential.begin(); 00640 bool is_stop = stop_pos == m_sequential.end(); 00641 if ( is_start && is_stop ) { 00642 // Nothing special. Taken care of by Keyed object manager 00643 } 00644 else if ( is_start || is_stop || use_tmp ) { 00645 std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos); 00646 tmp.insert(tmp.end(), stop_pos, m_sequential.end()); 00647 std::for_each(tmp.begin(), tmp.end(), traits::addRef); 00648 this->erase(m_sequential.begin(), m_sequential.end()); 00649 std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this)); 00650 return; 00651 } 00652 std::for_each(start_pos, stop_pos, _RemoveRelease(this)); 00653 seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules 00654 std::vector<void*>* v = (std::vector<void*>*)sptr; 00655 std::vector<void*>::iterator i1 = 00656 v->begin() + std::distance(m_sequential.begin(), start_pos); 00657 std::vector<void*>::iterator i2 = 00658 v->begin() + std::distance(m_sequential.begin(), stop_pos); 00659 m_cont.erase(i1, i2); 00660 } 00661 00662 #undef FORCE_INLINE 00663 #endif // GAUDIKERNEL_KEYEDCONTAINER_H