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  m_cont(std::move(other.m_cont)),
188  m_sequential(std::move(other.m_sequential))
189  {
190  m_cont.setup((void*)&m_sequential,(void**)&m_random);
191  std::for_each(begin(), end(), [this](ContainedObject* obj) {obj->setParent(this);});
192 
193  other.m_cont.setup((void*)&other.m_sequential, (void**)&other.m_random);
194  }
195  KeyedContainer(const KeyedContainer&) = delete;
197  ~KeyedContainer() override;
199 
205  const CLID& clID() const override { return this->classID(); }
208  static const CLID& classID() {
209  static CLID clid = contained_type::classID() + container_type::classID();
210  return clid;
211  }
213 
230  size_type numberOfObjects() const override { return m_sequential.size(); }
243  long add(ContainedObject* pObject) override;
244 
257  long remove(ContainedObject* pObject) override;
258 
262  ContainedObject* containedObject(long key_value) const override {
263  return i_object( traits::makeKey( key_value ) );
264  }
268  long index(const ContainedObject* p) const override;
274  virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
276 
282  size_type size() const { return m_sequential.size(); }
285  bool empty() const { return m_sequential.empty(); }
287  void reserve(size_type value) { m_cont.reserve(value); }
289  void clear() { erase(begin(), end()); }
295  virtual const std::vector<const ContainedObject*>* containedObjects() const;
300  StatusCode update() override;
302 
316  iterator begin() { return m_sequential.begin(); }
319  const_iterator begin() const { return m_sequential.begin(); }
321  iterator end() { return m_sequential.end(); }
323  const_iterator end() const { return m_sequential.end(); }
325  reverse_iterator rbegin() { return m_sequential.rbegin(); }
327  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
329  reverse_iterator rend() { return m_sequential.rend(); }
331  const_reverse_iterator rend() const { return m_sequential.rend(); }
333 
351  value_type object(const key_type& kval) const { return i_object(kval); }
352 
362  value_type operator()(const key_type& kval) const { return i_object(kval); }
364 
387  long erase(const key_type& kval) { return i_erase(0, kval); }
388 
409  long erase(const value_type val) {
410  return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
411  }
412 
433  long erase(iterator pos) { return erase(*pos); }
434 
443  void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
444 
463  const key_type& insert(const value_type val, const key_type& kval);
464 
486  const key_type& insert(const value_type val);
488 };
489 
490 
498 // Destructor
499 template <class DATATYPE, class MAPPING> inline
501 {
502  clear();
503  m_cont.clear();
504 }
505 
506 // Configure direct access
507 template <class DATATYPE, class MAPPING> inline
509 {
510  int count = 0;
511  m_cont.clearDirect();
512  typename seq_type::iterator i = m_sequential.begin();
513  typename seq_type::iterator s = m_sequential.end();
514  for ( ; i != s; i++ ) {
515  typename seq_type::value_type v = *i;
516  if ( v ) {
517  if ( !v->hasKey() ) {
518  traits::setKey(v, v->key());
519  traits::addRef(v);
520  }
521  long k0 = traits::hash(v->key());
522  if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
523  }
524  }
525  else {
526  ++count;
527  }
528  }
529  if ( count > 0 ) {
531  }
532  return StatusCode::SUCCESS;
533 }
534 
535 
536 // Retrieve the full content of the object container by reference.
537 template <class DATATYPE, class MAPPING> inline
541  ((0==m_cont.isDirect()) ? m_random : &m_sequential);
542 }
543 
544 template <class DATATYPE, class MAPPING> inline
547  const key_type& kval)
548 {
549  if ( val ) {
550  long k0 = traits::hash(kval);
551  if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
552  if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
553  if ( !val->hasKey() ) traits::setKey(val, kval);
554  traits::addRef(val);
555  return val->key();
556  }
557  }
558  }
559  // Cannot insert object...indicate bad object insertion...
561  return val->key();
562 }
563 
564 // Insert object
565 template <class DATATYPE, class MAPPING> //inline
568 {
569  if ( 0 != val ) {
570  if ( val->hasKey() ) {
571  if (m_cont.insert(this,val,val,traits::hash(val->key()))
573  traits::addRef(val);
574  return val->key();
575  }
576  }
577  long k0;
578  if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
579  traits::setKey(val, traits::makeKey(k0));
580  traits::addRef(val);
581  return val->key();
582  }
583  }
584  // Cannot insert object...indicate bad object insertion...
586  return val->key();
587 }
588 
589 template <class DATATYPE, class MAPPING> inline
591 {
592  const contained_type* ptr = dynamic_cast<const contained_type*>(p);
593  if ( ptr ) return traits::identifier(ptr->key());
594  return -1;
595 }
596 
597 // Retrieve the full content of the object container.
598 template <class DATATYPE, class MAPPING> inline
601 {
602  typename seq_type::const_iterator i = m_sequential.begin();
603  typename seq_type::const_iterator s = m_sequential.end();
604  vec.clear();
605  vec.reserve(size());
606  for ( ; i != s; i++ ) {
607  ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
608  vec.push_back(p);
609  }
610  return vec.size();
611 }
612 
613 // ObjectContainerBase overload: Add an object to the container.
614 template <class DATATYPE, class MAPPING> inline
616 {
617  return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
618 }
619 
620 // ObjectContainerBase overload: Remove an object from the container.
621 template <class DATATYPE, class MAPPING> inline
623 {
624  contained_type* p1 = dynamic_cast<contained_type*>(p);
625  if ( p1 ) { // Normal case; object still fully intact
626  return this->erase(p1);
627  }
628  else if ( p ) {
629  const ObjectContainerBase* par = p->parent();
630  // The following should never occur: object is in a funny state,
631  // Because the parent was explicitly set to NULL in the
632  // KeyeObject destructor.
633  // - It cannot be a KeyedObject: It would not have a parent
634  // - Still the parent is present: We are not in the destructor
635  // of KeyedObject
636  if ( par ) {
638  }
639  return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
640  : (long) Containers::OBJ_NOT_FOUND;
641  }
642  return (long) Containers::OBJ_NOT_FOUND;
643 }
644 
645 template <class DATATYPE, class MAPPING> inline
646 void
648  iterator stop_pos,
649  bool use_tmp)
650 {
651  bool is_start = start_pos == m_sequential.begin();
652  bool is_stop = stop_pos == m_sequential.end();
653  if ( is_start && is_stop ) {
654  // Nothing special. Taken care of by Keyed object manager
655  }
656  else if ( is_start || is_stop || use_tmp ) {
657  std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
658  tmp.insert(tmp.end(), stop_pos, m_sequential.end());
659  std::for_each(tmp.begin(), tmp.end(), traits::addRef);
660  this->erase(m_sequential.begin(), m_sequential.end());
661  std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
662  return;
663  }
664  std::for_each(start_pos, stop_pos, _RemoveRelease(this));
665  seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
668  v->begin() + std::distance(m_sequential.begin(), start_pos);
670  v->begin() + std::distance(m_sequential.begin(), stop_pos);
671  m_cont.erase(i1, i2);
672 }
673 
674 #undef FORCE_INLINE
675 #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.
constexpr struct Gaudi::Functional::details::insert_t insert
ObjectContainerBase * m_obj
template class KeyedContainer, KeyedContainer.h
STL namespace.
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:48
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.
KeyedContainer(KeyedContainer &&other)
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:50
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
void setParent(ObjectContainerBase *value)
Update parent member.
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)