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
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 >
65 {
66  friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
67 
68 public:
70  typedef DATATYPE contained_type;
72  typedef MAPPING container_type;
73 
80  typedef typename std::vector<contained_type*> seq_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:
106 
110  container_type m_cont;
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
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  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 {
156  m_obj->insert(p);
157  traits::release(p);
158  }
159  };
160 
162  struct _RemoveRelease {
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  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  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  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  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  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
492 {
493  erase(begin(), end());
494  m_cont.clear();
495 }
496 
497 // Configure direct access
498 template <class DATATYPE, class MAPPING> inline
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 ) {
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*>*
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
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...
552  return val->key();
553 }
554 
555 // Insert object
556 template <class DATATYPE, class MAPPING> //inline
559 {
560  if ( 0 != val ) {
561  if ( val->hasKey() ) {
562  if (m_cont.insert(this,val,val,traits::hash(val->key()))
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...
577  return val->key();
578 }
579 
580 template <class DATATYPE, class MAPPING> inline
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
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
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
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 ) {
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
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
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:78
Object was inserted into the container.
Definition: KeyedTraits.h:24
seq_type::reverse_iterator reverse_iterator
Sequential access: reverse iterator type used in sequential container.
Container traits class.
Definition: KeyedTraits.h:31
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.
static const CLID & classID()
Retrieve reference to class definition structure (static access)
Definition: DataObject.cpp:63
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
virtual long add(ContainedObject *pObject)
ObjectContainerBase overload: Add an object to the container.
seq_type m_sequential
Array to allow sequential access to the object (can be ordered).
std::vector< contained_type * > seq_type
General container specific type definitions.
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
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.
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.
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:22
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.
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.
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:58
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:30
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.
seq_type::const_iterator const_iterator
Sequential access: const iterator type used in sequential container.
unsigned int CLID
Class ID definition.
Definition: ClassID.h:9
#define FORCE_INLINE
tuple end
Definition: IOTest.py:101
Object was removed, but not deleted.
Definition: KeyedTraits.h:23
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
virtual long index(const ContainedObject *p) const
ObjectContainerBase overload: Retrieve the full long integer representation of the object's key from ...
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:21
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:210
const_iterator begin() const
Retrieve start const iterator.
virtual long remove(ContainedObject *pObject)
ObjectContainerBase overload: Remove an object from the container.
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.
#define GAUDI_API
Definition: Kernel.h:108
list i
Definition: ana.py:128
TO * reference(FROM *from)
Definition: KeyedObject.cpp:21
MAPPING container_type
Definition of the implementing container type.
seq_type * m_random
Array to allow random access to objects (not exposed)
void clear()
Clear the entire content and erase the objects from the container.