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;
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  virtual ~KeyedContainer();
189 
195  virtual const CLID& clID() const { return this->classID(); }
198  static const CLID& classID() {
199  static CLID clid = contained_type::classID() + container_type::classID();
200  return clid;
201  }
203 
220  virtual size_type numberOfObjects() const { return m_sequential.size(); }
233  virtual long add(ContainedObject* pObject);
234 
247  virtual long remove(ContainedObject* pObject);
248 
252  virtual ContainedObject* containedObject(long key_value) const {
253  return i_object( traits::makeKey( key_value ) );
254  }
258  virtual long index(const ContainedObject* p) const;
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  virtual StatusCode update();
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
virtual StatusCode update()
Provide empty placeholder for internal object reconfiguration callback.
Definition: DataObject.cpp:83
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)
static const CLID & classID()
Retrieve reference to class definition structure (static access)
Definition: DataObject.cpp:73
long erase(iterator pos)
Remove/erase object (identified by iterator) from the container.
virtual StatusCode update()
Reconfigure direct access to elements (Needed by POOL data loading) This function reuses the "update"...
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
void clear()
Clear content of the vector.
virtual long add(ContainedObject *pObject)
ObjectContainerBase overload: Add an object to the 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.
int key_type
Definition of the key-type to access object.
Definition: KeyedObject.h:32
virtual size_type numberOfObjects() const =0
Number of objects in the container.
ObjectContainerBase * m_obj
void clearDirect()
Clear all direct access fields.
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.
T end(T...args)
Containers::traits< container_type, contained_type > traits
Traits class definition.
void * object(long key) const
Retrieve object identified by a key from the container.
void * erase(long key, const void *obj)
Remove object from container (very inefficient if key is invalid)
static const CLID & classID()
Retrieve class ID.
seq_type::iterator iterator
Sequential access: iterator type used in sequential container.
virtual long add(ContainedObject *pObject)=0
Virtual functions (forwards to the concrete container definitions) Add an object to the 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.
virtual ~KeyedContainer()
Destructor.
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:45
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.
T push_back(T...args)
void reserve(long size)
Reserve buffer space.
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's cont...
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:68
FORCE_INLINE value_type i_object(const key_type &k) const
Internal function to access objects within the container.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
const_iterator end() const
Retrieve terminating const iterator.
virtual ContainedObject * containedObject(long key_value) const
ObjectContainerBase overload: Retrieve the object by reference given the long integer representation ...
seq_type::value_type value_type
Sequential access: definition of type stored in sequential container.
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:47
seq_type::const_iterator const_iterator
Sequential access: const iterator type used in sequential container.
long insert(ObjectContainerBase *b, ContainedObject *c, void *o, long *k)
Insert new object into container.
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
T clear(T...args)
#define FORCE_INLINE
T insert(T...args)
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)
virtual long index(const ContainedObject *p) const
ObjectContainerBase overload: Retrieve the full long integer representation of the object's key from ...
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.
virtual long index(const ContainedObject *obj) const =0
Distance of a given object from the beginning of its container.
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
void setup(void *seq, void **rndm)
Setup of the Map and the parent object.
const_iterator begin() const
Retrieve start const iterator.
virtual long remove(ContainedObject *pObject)
ObjectContainerBase overload: Remove an object from the container.
long isDirect() const
Check if the container is dirty.
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
list i
Definition: ana.py:128
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)
long insertDirect(ObjectContainerBase *b, ContainedObject *c, void *o, long k)
Insert element into direct access map.
void clear()
Clear the entire content and erase the objects from the container.
T rbegin(T...args)