KeyedContainer.h
Go to the documentation of this file.
1 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H
2 #define GAUDIKERNEL_KEYEDCONTAINER_H
3 
4 // Include files
5 #include <iterator>
6 #include <algorithm>
7 
8 namespace GaudiDict {
9  template <class T> struct KeyedContainerDict;
10 }
11 
12 // Framework include files
16 
17 // Forward declarations
18 // template <class T, class M> class KeyedContainer;
19 
20 #ifdef WIN32
21 #define FORCE_INLINE __forceinline
22 #else
23 #define FORCE_INLINE inline
24 #endif
25 
62 template <class DATATYPE, class MAPPING=Containers::HashMap >
64 {
65  friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
66 
67 public:
69  typedef DATATYPE contained_type;
71  typedef MAPPING container_type;
72 
79  typedef typename std::vector<contained_type*> seq_type;
82  typedef typename contained_type::key_type key_type;
84  typedef typename seq_type::value_type value_type;
86  typedef typename seq_type::reference reference;
88  typedef typename seq_type::const_reference const_reference;
90  typedef typename seq_type::iterator iterator;
92  typedef typename seq_type::const_iterator const_iterator;
94  typedef typename seq_type::reverse_iterator reverse_iterator;
98  typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
100 private:
105 
109  container_type m_cont;
112  seq_type m_sequential;
114  seq_type* m_random;
115 
117 #ifdef CHECK_KEYED_CONTAINER
118  value_type i_object(const key_type& k) const {
119  if ( 0 == m_cont.isDirect() ) {
120  if ( traits::checkBounds(m_random, k) ) {
121  value_type p = *(m_random->begin()+traits::hash(k));
122  if ( traits::checkKey(p, k) ) {
123  return p;
124  }
125  }
126  return 0;
127  }
128  value_type p = value_type(m_cont.object(traits::hash(k)));
129  return traits::checkKey(p, k) ? p : 0;
130  }
131 #else
132  FORCE_INLINE value_type i_object(const key_type& k) const {
133  return 0==m_cont.isDirect()
134  ? value_type(*(m_random->begin()+traits::hash(k)))
135  : value_type(m_cont.object(traits::hash(k)));
136  }
137 #endif
138  long i_erase(const_reference v, const key_type& k) {
140  value_type p = value_type(m_cont.erase(traits::hash(k), v));
141  if ( p ) {
142  if ( p->parent() == this ) {
143  p->setParent(0);
144  }
145  }
146  return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
147  : (long) Containers::OBJ_DELETED;
148  }
149 
151  struct _InsertRelease {
154  void operator()(value_type p) {
155  m_obj->insert(p);
156  traits::release(p);
157  }
158  };
159 
161  struct _RemoveRelease {
164  void operator()(value_type p) {
165  const ObjectContainerBase* par = p->parent();
166  if ( par == m_obj ) {
167  p->setParent(0);
168  }
169  traits::release(p);
170  }
171  };
173 
174 public:
178  KeyedContainer(void)
180  {
181  // avoid problems with strict-aliasing rules
182  seq_type** rptr = &m_random;
183  seq_type* sptr = &m_sequential;
184  m_cont.setup((void*)sptr,(void**)rptr);
185  }
187  ~KeyedContainer() override;
189 
195  const CLID& clID() const override { return this->classID(); }
198  static const CLID& classID() {
199  static CLID clid = contained_type::classID() + container_type::classID();
200  return clid;
201  }
203 
220  size_type numberOfObjects() const override { return m_sequential.size(); }
233  long add(ContainedObject* pObject) override;
234 
247  long remove(ContainedObject* pObject) override;
248 
252  ContainedObject* containedObject(long key_value) const override {
253  return i_object( traits::makeKey( key_value ) );
254  }
258  long index(const ContainedObject* p) const override;
264  virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
266 
272  size_type size() const { return m_sequential.size(); }
275  bool empty() const { return m_sequential.empty(); }
277  void reserve(size_type value) { m_cont.reserve(value); }
279  void clear() { erase(begin(), end()); }
285  virtual const std::vector<const ContainedObject*>* containedObjects() const;
290  StatusCode update() override;
292 
306  iterator begin() { return m_sequential.begin(); }
309  const_iterator begin() const { return m_sequential.begin(); }
311  iterator end() { return m_sequential.end(); }
313  const_iterator end() const { return m_sequential.end(); }
315  reverse_iterator rbegin() { return m_sequential.rbegin(); }
317  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
319  reverse_iterator rend() { return m_sequential.rend(); }
321  const_reverse_iterator rend() const { return m_sequential.rend(); }
323 
341  value_type object(const key_type& kval) const { return i_object(kval); }
342 
352  value_type operator()(const key_type& kval) const { return i_object(kval); }
354 
377  long erase(const key_type& kval) { return i_erase(0, kval); }
378 
399  long erase(const value_type val) {
400  return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
401  }
402 
423  long erase(iterator pos) { return erase(*pos); }
424 
433  void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
434 
453  const key_type& insert(const value_type val, const key_type& kval);
454 
476  const key_type& insert(const value_type val);
478 };
479 
480 
488 // Destructor
489 template <class DATATYPE, class MAPPING> inline
491 {
492  erase(begin(), end());
493  m_cont.clear();
494 }
495 
496 // Configure direct access
497 template <class DATATYPE, class MAPPING> inline
499 {
500  int count = 0;
501  m_cont.clearDirect();
502  typename seq_type::iterator i = m_sequential.begin();
503  typename seq_type::iterator s = m_sequential.end();
504  for ( ; i != s; i++ ) {
505  typename seq_type::value_type v = *i;
506  if ( v ) {
507  if ( !v->hasKey() ) {
508  traits::setKey(v, v->key());
509  traits::addRef(v);
510  }
511  long k0 = traits::hash(v->key());
512  if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
513  }
514  }
515  else {
516  ++count;
517  }
518  }
519  if ( count > 0 ) {
521  }
522  return StatusCode::SUCCESS;
523 }
524 
525 
526 // Retrieve the full content of the object container by reference.
527 template <class DATATYPE, class MAPPING> inline
531  ((0==m_cont.isDirect()) ? m_random : &m_sequential);
532 }
533 
534 template <class DATATYPE, class MAPPING> inline
537  const key_type& kval)
538 {
539  if ( val ) {
540  long k0 = traits::hash(kval);
541  if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
542  if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
543  if ( !val->hasKey() ) traits::setKey(val, kval);
544  traits::addRef(val);
545  return val->key();
546  }
547  }
548  }
549  // Cannot insert object...indicate bad object insertion...
551  return val->key();
552 }
553 
554 // Insert object
555 template <class DATATYPE, class MAPPING> //inline
558 {
559  if ( 0 != val ) {
560  if ( val->hasKey() ) {
561  if (m_cont.insert(this,val,val,traits::hash(val->key()))
563  traits::addRef(val);
564  return val->key();
565  }
566  }
567  long k0;
568  if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
569  traits::setKey(val, traits::makeKey(k0));
570  traits::addRef(val);
571  return val->key();
572  }
573  }
574  // Cannot insert object...indicate bad object insertion...
576  return val->key();
577 }
578 
579 template <class DATATYPE, class MAPPING> inline
581 {
582  const contained_type* ptr = dynamic_cast<const contained_type*>(p);
583  if ( ptr ) return traits::identifier(ptr->key());
584  return -1;
585 }
586 
587 // Retrieve the full content of the object container.
588 template <class DATATYPE, class MAPPING> inline
591 {
592  typename seq_type::const_iterator i = m_sequential.begin();
593  typename seq_type::const_iterator s = m_sequential.end();
594  vec.clear();
595  vec.reserve(size());
596  for ( ; i != s; i++ ) {
597  ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
598  vec.push_back(p);
599  }
600  return vec.size();
601 }
602 
603 // ObjectContainerBase overload: Add an object to the container.
604 template <class DATATYPE, class MAPPING> inline
606 {
607  return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
608 }
609 
610 // ObjectContainerBase overload: Remove an object from the container.
611 template <class DATATYPE, class MAPPING> inline
613 {
614  contained_type* p1 = dynamic_cast<contained_type*>(p);
615  if ( p1 ) { // Normal case; object still fully intact
616  return this->erase(p1);
617  }
618  else if ( p ) {
619  const ObjectContainerBase* par = p->parent();
620  // The following should never occur: object is in a funny state,
621  // Because the parent was explicitly set to NULL in the
622  // KeyeObject destructor.
623  // - It cannot be a KeyedObject: It would not have a parent
624  // - Still the parent is present: We are not in the destructor
625  // of KeyedObject
626  if ( par ) {
628  }
629  return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
630  : (long) Containers::OBJ_NOT_FOUND;
631  }
632  return (long) Containers::OBJ_NOT_FOUND;
633 }
634 
635 template <class DATATYPE, class MAPPING> inline
636 void
638  iterator stop_pos,
639  bool use_tmp)
640 {
641  bool is_start = start_pos == m_sequential.begin();
642  bool is_stop = stop_pos == m_sequential.end();
643  if ( is_start && is_stop ) {
644  // Nothing special. Taken care of by Keyed object manager
645  }
646  else if ( is_start || is_stop || use_tmp ) {
647  std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
648  tmp.insert(tmp.end(), stop_pos, m_sequential.end());
649  std::for_each(tmp.begin(), tmp.end(), traits::addRef);
650  this->erase(m_sequential.begin(), m_sequential.end());
651  std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
652  return;
653  }
654  std::for_each(start_pos, stop_pos, _RemoveRelease(this));
655  seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
658  v->begin() + std::distance(m_sequential.begin(), start_pos);
660  v->begin() + std::distance(m_sequential.begin(), stop_pos);
661  m_cont.erase(i1, i2);
662 }
663 
664 #undef FORCE_INLINE
665 #endif // GAUDIKERNEL_KEYEDCONTAINER_H
virtual const std::vector< const ContainedObject * > * containedObjects() const
Retrieve the full content of the object container by reference.
reverse_iterator rbegin()
reverse_iterator returns the beginning of the reversed container
Object was inserted into the container.
Definition: KeyedTraits.h:23
seq_type::reverse_iterator reverse_iterator
Sequential access: reverse iterator type used in sequential container.
T empty(T...args)
Container traits class.
Definition: KeyedTraits.h:30
seq_type::const_reference const_reference
Sequential access: const reference type used in sequential container.
void reserve(size_type value)
Reserve place for "value" objects in the container.
value_type object(const key_type &kval) const
Object access by key.
T distance(T...args)
long erase(iterator pos)
Remove/erase object (identified by iterator) from the container.
long add(ContainedObject *pObject) override
ObjectContainerBase overload: Add an object to the container.
size_t size_type
size_type, to conform the STL container interface
const_reverse_iterator rbegin() const
const reverse_iterator returns the beginning of the reversed container
T rend(T...args)
seq_type m_sequential
Array to allow sequential access to the object (can be ordered).
seq_type::reference reference
Sequential access: reference type used in sequential container.
ObjectContainerBase * m_obj
template class KeyedContainer, KeyedContainer.h
KeyedContainer< DATATYPE, MAPPING > * m_obj
long erase(const key_type &kval)
Remove/erase object (identified by key) from the container.
long remove(ContainedObject *pObject) override
ObjectContainerBase overload: Remove an object from the container.
T end(T...args)
Containers::traits< container_type, contained_type > traits
Traits class definition.
static const CLID & classID()
Retrieve class ID.
seq_type::iterator iterator
Sequential access: iterator type used in sequential container.
Internal functor for insertion of objects.
DATATYPE contained_type
Definition of the contained object type.
value_type operator()(const key_type &kval) const
STL algorithms support for object access.
Object was removed from the container and deleted.
Definition: KeyedTraits.h:21
const ObjectContainerBase * parent() const
Access to parent object.
const key_type & insert(const value_type val, const key_type &kval)
Insert entry to the container with a valid key.
GAUDI_API void cannotInsertToContainer()
Function to be called to indicate that an object cannot be inserted to the container.
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:47
const_reverse_iterator rend() const
const reverse_iterator pointing to the end of the reversed container
bool empty() const
For consistency with STL: check if container is empty.
long index(const ContainedObject *p) const override
ObjectContainerBase overload: Retrieve the full long integer representation of the object&#39;s key from ...
T push_back(T...args)
reverse_iterator rend()
reverse_iterator pointing to the end of the reversed container
_RemoveRelease(ObjectContainerBase *p)
GAUDI_API void invalidContainerOperation()
Function to be called to indicate that an operation should be performed on the container or it&#39;s cont...
FORCE_INLINE value_type i_object(const key_type &k) const
Internal function to access objects within the container.
StatusCode update() override
Reconfigure direct access to elements (Needed by POOL data loading) This function reuses the "update"...
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
const_iterator end() const
Retrieve terminating const iterator.
seq_type::value_type value_type
Sequential access: definition of type stored in sequential container.
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:49
ContainedObject * containedObject(long key_value) const override
ObjectContainerBase overload: Retrieve the object by reference given the long integer representation ...
seq_type::const_iterator const_iterator
Sequential access: const iterator type used in sequential container.
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
T clear(T...args)
#define FORCE_INLINE
T insert(T...args)
~KeyedContainer() override
Destructor.
Object was removed, but not deleted.
Definition: KeyedTraits.h:22
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
T size(T...args)
T begin(T...args)
long erase(const value_type val)
Remove/erase object (identified by pointer value) from the container.
_InsertRelease(KeyedContainer< DATATYPE, MAPPING > *p)
iterator end()
Retrieve terminating iterator.
Object not present in the container.
Definition: KeyedTraits.h:20
contained_type::key_type key_type
Definition of the key type: re-use definition of contained type.
Internal functor for insertion of objects.
string s
Definition: gaudirun.py:245
const_iterator begin() const
Retrieve start const iterator.
ObjectContainerBase is the base class for Gaudi container classes.
seq_type::const_reverse_iterator const_reverse_iterator
Sequential access: const reverse iterator type used in sequential container.
T for_each(T...args)
#define GAUDI_API
Definition: Kernel.h:107
TO * reference(FROM *from)
Definition: KeyedObject.cpp:20
MAPPING container_type
Definition of the implementing container type.
seq_type * m_random
Array to allow random access to objects (not exposed)
T reserve(T...args)
void clear()
Clear the entire content and erase the objects from the container.
T rbegin(T...args)