Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v28r2p1 (f1a77ff4)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  ObjectContainerBase(std::move(other)),
188  m_cont(std::move(other.m_cont)),
189  m_sequential(std::move(other.m_sequential))
190  {
191  m_cont.setup((void*)&m_sequential,(void**)&m_random);
192  std::for_each(begin(), end(), [this](ContainedObject* obj) {obj->setParent(this);});
193 
194  other.m_cont.setup((void*)&other.m_sequential, (void**)&other.m_random);
195  }
196  KeyedContainer(const KeyedContainer&) = delete;
198  ~KeyedContainer() override;
200 
206  const CLID& clID() const override { return this->classID(); }
209  static const CLID& classID() {
210  static CLID clid = contained_type::classID() + container_type::classID();
211  return clid;
212  }
214 
231  size_type numberOfObjects() const override { return m_sequential.size(); }
244  long add(ContainedObject* pObject) override;
245 
258  long remove(ContainedObject* pObject) override;
259 
263  ContainedObject* containedObject(long key_value) const override {
264  return i_object( traits::makeKey( key_value ) );
265  }
269  long index(const ContainedObject* p) const override;
275  virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
277 
283  size_type size() const { return m_sequential.size(); }
286  bool empty() const { return m_sequential.empty(); }
288  void reserve(size_type value) { m_cont.reserve(value); }
290  void clear() { erase(begin(), end()); }
296  virtual const std::vector<const ContainedObject*>* containedObjects() const;
301  StatusCode update() override;
303 
317  iterator begin() { return m_sequential.begin(); }
320  const_iterator begin() const { return m_sequential.begin(); }
322  iterator end() { return m_sequential.end(); }
324  const_iterator end() const { return m_sequential.end(); }
326  reverse_iterator rbegin() { return m_sequential.rbegin(); }
328  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
330  reverse_iterator rend() { return m_sequential.rend(); }
332  const_reverse_iterator rend() const { return m_sequential.rend(); }
334 
352  value_type object(const key_type& kval) const { return i_object(kval); }
353 
363  value_type operator()(const key_type& kval) const { return i_object(kval); }
365 
388  long erase(const key_type& kval) { return i_erase(0, kval); }
389 
410  long erase(const value_type val) {
411  return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
412  }
413 
434  long erase(iterator pos) { return erase(*pos); }
435 
444  void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
445 
464  const key_type& insert(const value_type val, const key_type& kval);
465 
487  const key_type& insert(const value_type val);
489 };
490 
491 
499 // Destructor
500 template <class DATATYPE, class MAPPING> inline
502 {
503  clear();
504  m_cont.clear();
505 }
506 
507 // Configure direct access
508 template <class DATATYPE, class MAPPING> inline
510 {
511  int count = 0;
512  m_cont.clearDirect();
513  typename seq_type::iterator i = m_sequential.begin();
514  typename seq_type::iterator s = m_sequential.end();
515  for ( ; i != s; i++ ) {
516  typename seq_type::value_type v = *i;
517  if ( v ) {
518  if ( !v->hasKey() ) {
519  traits::setKey(v, v->key());
520  traits::addRef(v);
521  }
522  long k0 = traits::hash(v->key());
523  if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
524  }
525  }
526  else {
527  ++count;
528  }
529  }
530  if ( count > 0 ) {
532  }
533  return StatusCode::SUCCESS;
534 }
535 
536 
537 // Retrieve the full content of the object container by reference.
538 template <class DATATYPE, class MAPPING> inline
542  ((0==m_cont.isDirect()) ? m_random : &m_sequential);
543 }
544 
545 template <class DATATYPE, class MAPPING> inline
548  const key_type& kval)
549 {
550  if ( val ) {
551  long k0 = traits::hash(kval);
552  if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
553  if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
554  if ( !val->hasKey() ) traits::setKey(val, kval);
555  traits::addRef(val);
556  return val->key();
557  }
558  }
559  }
560  // Cannot insert object...indicate bad object insertion...
562  return val->key();
563 }
564 
565 // Insert object
566 template <class DATATYPE, class MAPPING> //inline
569 {
570  if ( 0 != val ) {
571  if ( val->hasKey() ) {
572  if (m_cont.insert(this,val,val,traits::hash(val->key()))
574  traits::addRef(val);
575  return val->key();
576  }
577  }
578  long k0;
579  if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
580  traits::setKey(val, traits::makeKey(k0));
581  traits::addRef(val);
582  return val->key();
583  }
584  }
585  // Cannot insert object...indicate bad object insertion...
587  return val->key();
588 }
589 
590 template <class DATATYPE, class MAPPING> inline
592 {
593  const contained_type* ptr = dynamic_cast<const contained_type*>(p);
594  if ( ptr ) return traits::identifier(ptr->key());
595  return -1;
596 }
597 
598 // Retrieve the full content of the object container.
599 template <class DATATYPE, class MAPPING> inline
602 {
603  typename seq_type::const_iterator i = m_sequential.begin();
604  typename seq_type::const_iterator s = m_sequential.end();
605  vec.clear();
606  vec.reserve(size());
607  for ( ; i != s; i++ ) {
608  ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
609  vec.push_back(p);
610  }
611  return vec.size();
612 }
613 
614 // ObjectContainerBase overload: Add an object to the container.
615 template <class DATATYPE, class MAPPING> inline
617 {
618  return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
619 }
620 
621 // ObjectContainerBase overload: Remove an object from the container.
622 template <class DATATYPE, class MAPPING> inline
624 {
625  contained_type* p1 = dynamic_cast<contained_type*>(p);
626  if ( p1 ) { // Normal case; object still fully intact
627  return this->erase(p1);
628  }
629  else if ( p ) {
630  const ObjectContainerBase* par = p->parent();
631  // The following should never occur: object is in a funny state,
632  // Because the parent was explicitly set to NULL in the
633  // KeyeObject destructor.
634  // - It cannot be a KeyedObject: It would not have a parent
635  // - Still the parent is present: We are not in the destructor
636  // of KeyedObject
637  if ( par ) {
639  }
640  return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
641  : (long) Containers::OBJ_NOT_FOUND;
642  }
643  return (long) Containers::OBJ_NOT_FOUND;
644 }
645 
646 template <class DATATYPE, class MAPPING> inline
647 void
649  iterator stop_pos,
650  bool use_tmp)
651 {
652  bool is_start = start_pos == m_sequential.begin();
653  bool is_stop = stop_pos == m_sequential.end();
654  if ( is_start && is_stop ) {
655  // Nothing special. Taken care of by Keyed object manager
656  }
657  else if ( is_start || is_stop || use_tmp ) {
658  std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
659  tmp.insert(tmp.end(), stop_pos, m_sequential.end());
660  std::for_each(tmp.begin(), tmp.end(), traits::addRef);
661  this->erase(m_sequential.begin(), m_sequential.end());
662  std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
663  return;
664  }
665  std::for_each(start_pos, stop_pos, _RemoveRelease(this));
666  seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
669  v->begin() + std::distance(m_sequential.begin(), start_pos);
671  v->begin() + std::distance(m_sequential.begin(), stop_pos);
672  m_cont.erase(i1, i2);
673 }
674 
675 #undef FORCE_INLINE
676 #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)