| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
KeyedContainer.h
Go to the documentation of this file.
1 // $Id $
2 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H
3 #define GAUDIKERNEL_KEYEDCONTAINER_H
4
5 // Include files
6 #include <iterator>
7 #include <algorithm>
8
9 namespace GaudiDict {
10 template <class T> struct KeyedContainerDict;
11 }
12
13 // Framework include files
14 #include "GaudiKernel/ObjectContainerBase.h"
15 #include "GaudiKernel/KeyedObjectManager.h"
16 #include "GaudiKernel/KeyedObject.h"
17
18 // Forward declarations
19 // template <class T, class M> class KeyedContainer;
20
21 #ifdef WIN32
22 #define FORCE_INLINE __forceinline
23 #else
24 #define FORCE_INLINE inline
25 #endif
26
63 template <class DATATYPE, class MAPPING=Containers::HashMap >
64 class GAUDI_API KeyedContainer: public ObjectContainerBase
65 {
66 friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
67
68 public:
70 typedef DATATYPE contained_type;
72 typedef MAPPING container_type;
73
80
81 typedef typename std::vector<contained_type*> seq_type;
83 typedef typename contained_type::key_type key_type;
85 typedef typename seq_type::value_type value_type;
87 typedef typename seq_type::reference reference;
89 typedef typename seq_type::const_reference const_reference;
91 typedef typename seq_type::iterator iterator;
93 typedef typename seq_type::const_iterator const_iterator;
95 typedef typename seq_type::reverse_iterator reverse_iterator;
99 typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
101 private:
105 typedef typename Containers::traits<container_type, contained_type> traits;
106
110
111 container_type m_cont;
113 seq_type m_sequential;
115 seq_type* m_random;
116
118 #ifdef CHECK_KEYED_CONTAINER
119 value_type i_object(const key_type& k) const {
120 if ( 0 == m_cont.isDirect() ) {
121 if ( traits::checkBounds(m_random, k) ) {
122 value_type p = *(m_random->begin()+traits::hash(k));
123 if ( traits::checkKey(p, k) ) {
124 return p;
125 }
126 }
127 return 0;
128 }
129 value_type p = value_type(m_cont.object(traits::hash(k)));
130 return traits::checkKey(p, k) ? p : 0;
131 }
132 #else
133 FORCE_INLINE value_type i_object(const key_type& k) const {
134 return 0==m_cont.isDirect()
135 ? value_type(*(m_random->begin()+traits::hash(k)))
136 : value_type(m_cont.object(traits::hash(k)));
137 }
138 #endif
139
140 long i_erase(const_reference v, const key_type& k) {
141 value_type p = value_type(m_cont.erase(traits::hash(k), v));
142 if ( p ) {
143 if ( p->parent() == this ) {
144 p->setParent(0);
145 }
146 }
147 return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
148 : (long) Containers::OBJ_DELETED;
149 }
150
152 struct _InsertRelease {
153 KeyedContainer<DATATYPE,MAPPING>* m_obj;
154 _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
155 void operator()(value_type p) {
156 m_obj->insert(p);
157 traits::release(p);
158 }
159 };
160
162 struct _RemoveRelease {
163 ObjectContainerBase* m_obj;
164 _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
165 void operator()(value_type p) {
166 const ObjectContainerBase* par = p->parent();
167 if ( par == m_obj ) {
168 p->setParent(0);
169 }
170 traits::release(p);
171 }
172 };
174
175 public:
179
180 KeyedContainer(void)
181 {
182 // avoid problems with strict-aliasing rules
183 seq_type** rptr = &m_random;
184 seq_type* sptr = &m_sequential;
185 m_cont.setup((void*)sptr,(void**)rptr);
186 }
188 virtual ~KeyedContainer();
190
196
197 virtual const CLID& clID() const { return this->classID(); }
199 static const CLID& classID() {
200 static CLID clid = contained_type::classID() + container_type::classID();
201 return clid;
202 }
204
221
222 virtual size_type numberOfObjects() const { return m_sequential.size(); }
234 virtual long add(ContainedObject* pObject);
235
248 virtual long remove(ContainedObject* pObject);
249
253 virtual ContainedObject* containedObject(long key_value) const {
254 return i_object( traits::makeKey( key_value ) );
255 }
259 virtual long index(const ContainedObject* p) const;
265 virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
267
273
274 size_type size() const { return m_sequential.size(); }
276 bool empty() const { return m_sequential.empty(); }
278 void reserve(size_type value) { m_cont.reserve(value); }
280 void clear() { erase(begin(), end()); }
286 virtual const std::vector<const ContainedObject*>* containedObjects() const;
291 virtual StatusCode update();
293
307
308 iterator begin() { return m_sequential.begin(); }
310 const_iterator begin() const { return m_sequential.begin(); }
312 iterator end() { return m_sequential.end(); }
314 const_iterator end() const { return m_sequential.end(); }
316 reverse_iterator rbegin() { return m_sequential.rbegin(); }
318 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
320 reverse_iterator rend() { return m_sequential.rend(); }
322 const_reverse_iterator rend() const { return m_sequential.rend(); }
324
342 value_type object(const key_type& kval) const { return i_object(kval); }
343
353 value_type operator()(const key_type& kval) const { return i_object(kval); }
355
378 long erase(const key_type& kval) { return i_erase(0, kval); }
379
400 long erase(const value_type val) {
401 return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
402 }
403
424 long erase(iterator pos) { return erase(*pos); }
425
434 void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
435
454 const key_type& insert(const value_type val, const key_type& kval);
455
477 const key_type& insert(const value_type val);
479 };
480
481
489 // Destructor
490 template <class DATATYPE, class MAPPING> inline
491 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
492 {
493 erase(begin(), end());
494 m_cont.clear();
495 }
496
497 // Configure direct access
498 template <class DATATYPE, class MAPPING> inline
499 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
500 {
501 int count = 0;
502 m_cont.clearDirect();
503 typename seq_type::iterator i = m_sequential.begin();
504 typename seq_type::iterator s = m_sequential.end();
505 for ( ; i != s; i++ ) {
506 typename seq_type::value_type v = *i;
507 if ( v ) {
508 if ( !v->hasKey() ) {
509 traits::setKey(v, v->key());
510 traits::addRef(v);
511 }
512 long k0 = traits::hash(v->key());
513 if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
514 }
515 }
516 else {
517 ++count;
518 }
519 }
520 if ( count > 0 ) {
521 Containers::cannotInsertToContainer();
522 }
523 return StatusCode::SUCCESS;
524 }
525
526
527 // Retrieve the full content of the object container by reference.
528 template <class DATATYPE, class MAPPING> inline
529 const std::vector<const ContainedObject*>*
530 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const {
531 return (const std::vector<const ContainedObject*>*)
532 ((0==m_cont.isDirect()) ? m_random : &m_sequential);
533 }
534
535 template <class DATATYPE, class MAPPING> inline
536 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
537 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
538 const key_type& kval)
539 {
540 if ( val ) {
541 long k0 = traits::hash(kval);
542 if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
543 if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
544 if ( !val->hasKey() ) traits::setKey(val, kval);
545 traits::addRef(val);
546 return val->key();
547 }
548 }
549 }
550 // Cannot insert object...indicate bad object insertion...
551 Containers::cannotInsertToContainer();
552 return val->key();
553 }
554
555 // Insert object
556 template <class DATATYPE, class MAPPING> //inline
557 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
558 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
559 {
560 if ( 0 != val ) {
561 if ( val->hasKey() ) {
562 if (m_cont.insert(this,val,val,traits::hash(val->key()))
563 == Containers::OBJ_INSERTED) {
564 traits::addRef(val);
565 return val->key();
566 }
567 }
568 long k0;
569 if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
570 traits::setKey(val, traits::makeKey(k0));
571 traits::addRef(val);
572 return val->key();
573 }
574 }
575 // Cannot insert object...indicate bad object insertion...
576 Containers::cannotInsertToContainer();
577 return val->key();
578 }
579
580 template <class DATATYPE, class MAPPING> inline
581 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
582 {
583 const contained_type* ptr = dynamic_cast<const contained_type*>(p);
584 if ( ptr ) return traits::identifier(ptr->key());
585 return -1;
586 }
587
588 // Retrieve the full content of the object container.
589 template <class DATATYPE, class MAPPING> inline
590 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
591 (std::vector<ContainedObject*>& vec) const
592 {
593 typename seq_type::const_iterator i = m_sequential.begin();
594 typename seq_type::const_iterator s = m_sequential.end();
595 vec.clear();
596 vec.reserve(size());
597 for ( ; i != s; i++ ) {
598 ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
599 vec.push_back(p);
600 }
601 return vec.size();
602 }
603
604 // ObjectContainerBase overload: Add an object to the container.
605 template <class DATATYPE, class MAPPING> inline
606 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
607 {
608 return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
609 }
610
611 // ObjectContainerBase overload: Remove an object from the container.
612 template <class DATATYPE, class MAPPING> inline
613 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
614 {
615 contained_type* p1 = dynamic_cast<contained_type*>(p);
616 if ( p1 ) { // Normal case; object still fully intact
617 return this->erase(p1);
618 }
619 else if ( p ) {
620 const ObjectContainerBase* par = p->parent();
621 // The following should never occur: object is in a funny state,
622 // Because the parent was explicitly set to NULL in the
623 // KeyeObject destructor.
624 // - It cannot be a KeyedObject: It would not have a parent
625 // - Still the parent is present: We are not in the destructor
626 // of KeyedObject
627 if ( par ) {
628 Containers::invalidContainerOperation();
629 }
630 return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
631 : (long) Containers::OBJ_NOT_FOUND;
632 }
633 return (long) Containers::OBJ_NOT_FOUND;
634 }
635
636 template <class DATATYPE, class MAPPING> inline
637 void
638 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
639 iterator stop_pos,
640 bool use_tmp)
641 {
642 bool is_start = start_pos == m_sequential.begin();
643 bool is_stop = stop_pos == m_sequential.end();
644 if ( is_start && is_stop ) {
645 // Nothing special. Taken care of by Keyed object manager
646 }
647 else if ( is_start || is_stop || use_tmp ) {
648 std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
649 tmp.insert(tmp.end(), stop_pos, m_sequential.end());
650 std::for_each(tmp.begin(), tmp.end(), traits::addRef);
651 this->erase(m_sequential.begin(), m_sequential.end());
652 std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
653 return;
654 }
655 std::for_each(start_pos, stop_pos, _RemoveRelease(this));
656 seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
657 std::vector<void*>* v = (std::vector<void*>*)sptr;
658 std::vector<void*>::iterator i1 =
659 v->begin() + std::distance(m_sequential.begin(), start_pos);
660 std::vector<void*>::iterator i2 =
661 v->begin() + std::distance(m_sequential.begin(), stop_pos);
662 m_cont.erase(i1, i2);
663 }
664
665 #undef FORCE_INLINE
666 #endif // GAUDIKERNEL_KEYEDCONTAINER_H