The Gaudi Framework  v30r3 (a5ef0a68)
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 <algorithm>
6 #include <iterator>
7 
8 namespace GaudiDict
9 {
10  template <class T>
12 }
13 
14 // Framework include files
18 
19 // Forward declarations
20 // template <class T, class M> class KeyedContainer;
21 
22 #ifdef WIN32
23 #define FORCE_INLINE __forceinline
24 #else
25 #define FORCE_INLINE inline
26 #endif
27 
64 template <class DATATYPE, class MAPPING = Containers::HashMap>
66 {
67  friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
68 
69 public:
71  typedef DATATYPE contained_type;
73  typedef MAPPING container_type;
74 
81  typedef typename std::vector<contained_type*> seq_type;
84  typedef typename contained_type::key_type key_type;
86  typedef typename seq_type::value_type value_type;
88  typedef typename seq_type::reference reference;
90  typedef typename seq_type::const_reference const_reference;
92  typedef typename seq_type::iterator iterator;
94  typedef typename seq_type::const_iterator const_iterator;
96  typedef typename seq_type::reverse_iterator reverse_iterator;
100  typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
102 private:
107 
111  container_type m_cont;
114  seq_type m_sequential;
116  seq_type* m_random;
117 
119 #ifdef CHECK_KEYED_CONTAINER
120  value_type i_object( const key_type& k ) const
121  {
122  if ( 0 == m_cont.isDirect() ) {
123  if ( traits::checkBounds( m_random, k ) ) {
124  value_type p = *( m_random->begin() + traits::hash( k ) );
125  if ( traits::checkKey( p, k ) ) {
126  return p;
127  }
128  }
129  return 0;
130  }
131  value_type p = value_type( m_cont.object( traits::hash( k ) ) );
132  return traits::checkKey( p, k ) ? p : 0;
133  }
134 #else
135  FORCE_INLINE value_type i_object( const key_type& k ) const
136  {
137  return 0 == m_cont.isDirect() ? value_type( *( m_random->begin() + traits::hash( k ) ) )
138  : value_type( m_cont.object( traits::hash( k ) ) );
139  }
140 #endif
141  long i_erase( const_reference v, const key_type& k )
143  {
144  value_type p = value_type( m_cont.erase( traits::hash( k ), v ) );
145  if ( p ) {
146  if ( p->parent() == this ) {
147  p->setParent( 0 );
148  }
149  }
150  return traits::release( p ) <= 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_DELETED;
151  }
152 
154  struct _InsertRelease {
157  void operator()( value_type p )
158  {
159  m_obj->insert( p );
160  traits::release( p );
161  }
162  };
163 
165  struct _RemoveRelease {
167  _RemoveRelease( ObjectContainerBase* p ) : m_obj( p ) {}
168  void operator()( value_type p )
169  {
170  const ObjectContainerBase* par = p->parent();
171  if ( par == m_obj ) {
172  p->setParent( 0 );
173  }
174  traits::release( p );
175  }
176  };
178 
179 public:
183  KeyedContainer( void )
185  {
186  // avoid problems with strict-aliasing rules
187  seq_type** rptr = &m_random;
188  seq_type* sptr = &m_sequential;
189  m_cont.setup( (void*)sptr, (void**)rptr );
190  }
192  : ObjectContainerBase( std::move( other ) )
193  , m_cont( std::move( other.m_cont ) )
194  , m_sequential( std::move( other.m_sequential ) )
195  {
196  m_cont.setup( (void*)&m_sequential, (void**)&m_random );
197  std::for_each( begin(), end(), [this]( ContainedObject* obj ) { obj->setParent( this ); } );
198 
199  other.m_cont.setup( (void*)&other.m_sequential, (void**)&other.m_random );
200  }
201  KeyedContainer( const KeyedContainer& ) = delete;
203  ~KeyedContainer() override;
205 
211  const CLID& clID() const override { return this->classID(); }
214  static const CLID& classID()
215  {
216  static CLID clid = contained_type::classID() + container_type::classID();
217  return clid;
218  }
220 
237  size_type numberOfObjects() const override { return m_sequential.size(); }
250  long add( ContainedObject* pObject ) override;
251 
264  long remove( ContainedObject* pObject ) override;
265 
269  ContainedObject* containedObject( long key_value ) const override { return i_object( traits::makeKey( key_value ) ); }
273  long index( const ContainedObject* p ) const override;
279  virtual size_type containedObjects( std::vector<ContainedObject*>& v ) const;
281 
287  size_type size() const { return m_sequential.size(); }
290  bool empty() const { return m_sequential.empty(); }
292  void reserve( size_type value ) { m_cont.reserve( value ); }
294  void clear() { erase( begin(), end() ); }
300  virtual const std::vector<const ContainedObject*>* containedObjects() const;
305  StatusCode update() override;
307 
321  iterator begin() { return m_sequential.begin(); }
324  const_iterator begin() const { return m_sequential.begin(); }
326  iterator end() { return m_sequential.end(); }
328  const_iterator end() const { return m_sequential.end(); }
330  reverse_iterator rbegin() { return m_sequential.rbegin(); }
332  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
334  reverse_iterator rend() { return m_sequential.rend(); }
336  const_reverse_iterator rend() const { return m_sequential.rend(); }
338 
356  value_type object( const key_type& kval ) const { return i_object( kval ); }
357 
367  value_type operator()( const key_type& kval ) const { return i_object( kval ); }
369 
392  long erase( const key_type& kval ) { return i_erase( 0, kval ); }
393 
414  long erase( const value_type val ) { return ( val ) ? i_erase( val, val->key() ) : (long)Containers::OBJ_NOT_FOUND; }
415 
436  long erase( iterator pos ) { return erase( *pos ); }
437 
446  void erase( iterator pos_start, iterator pos_stop, bool use_temp = false );
447 
466  const key_type& insert( const value_type val, const key_type& kval );
467 
489  const key_type& insert( const value_type val );
491 };
492 
500 // Destructor
501 template <class DATATYPE, class MAPPING>
503 {
504  clear();
505  m_cont.clear();
506 }
507 
508 // Configure direct access
509 template <class DATATYPE, class MAPPING>
511 {
512  int count = 0;
513  m_cont.clearDirect();
514  typename seq_type::iterator i = m_sequential.begin();
515  typename seq_type::iterator s = m_sequential.end();
516  for ( ; i != s; i++ ) {
517  typename seq_type::value_type v = *i;
518  if ( v ) {
519  if ( !v->hasKey() ) {
520  traits::setKey( v, v->key() );
521  traits::addRef( v );
522  }
523  long k0 = traits::hash( v->key() );
524  if ( m_cont.insertDirect( this, v, v, k0 ) == Containers::OBJ_INSERTED ) {
525  }
526  } else {
527  ++count;
528  }
529  }
530  if ( count > 0 ) {
532  }
533  return StatusCode::SUCCESS;
534 }
535 
536 // Retrieve the full content of the object container by reference.
537 template <class DATATYPE, class MAPPING>
539 {
540  return (const std::vector<const ContainedObject*>*)( ( 0 == m_cont.isDirect() ) ? m_random : &m_sequential );
541 }
542 
543 template <class DATATYPE, class MAPPING>
544 inline const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
546 {
547  if ( val ) {
548  long k0 = traits::hash( kval );
549  if ( !val->hasKey() || ( traits::hash( val->key() ) == k0 ) ) {
550  if ( m_cont.insert( this, val, val, k0 ) == Containers::OBJ_INSERTED ) {
551  if ( !val->hasKey() ) traits::setKey( val, kval );
552  traits::addRef( val );
553  return val->key();
554  }
555  }
556  }
557  // Cannot insert object...indicate bad object insertion...
559  return val->key();
560 }
561 
562 // Insert object
563 template <class DATATYPE, class MAPPING> // inline
566 {
567  if ( 0 != val ) {
568  if ( val->hasKey() ) {
569  if ( m_cont.insert( this, val, val, traits::hash( val->key() ) ) == Containers::OBJ_INSERTED ) {
570  traits::addRef( val );
571  return val->key();
572  }
573  }
574  long k0;
575  if ( m_cont.insert( this, val, val, &k0 ) == Containers::OBJ_INSERTED ) {
576  traits::setKey( val, traits::makeKey( k0 ) );
577  traits::addRef( val );
578  return val->key();
579  }
580  }
581  // Cannot insert object...indicate bad object insertion...
583  return val->key();
584 }
585 
586 template <class DATATYPE, class MAPPING>
588 {
589  const contained_type* ptr = dynamic_cast<const contained_type*>( p );
590  if ( ptr ) return traits::identifier( ptr->key() );
591  return -1;
592 }
593 
594 // Retrieve the full content of the object container.
595 template <class DATATYPE, class MAPPING>
598 {
599  typename seq_type::const_iterator i = m_sequential.begin();
600  typename seq_type::const_iterator s = m_sequential.end();
601  vec.clear();
602  vec.reserve( size() );
603  for ( ; i != s; i++ ) {
604  ContainedObject* p = const_cast<typename seq_type::value_type>( *i );
605  vec.push_back( p );
606  }
607  return vec.size();
608 }
609 
610 // ObjectContainerBase overload: Add an object to the container.
611 template <class DATATYPE, class MAPPING>
613 {
614  return traits::identifier( insert( dynamic_cast<typename seq_type::value_type>( pObject ) ) );
615 }
616 
617 // ObjectContainerBase overload: Remove an object from the container.
618 template <class DATATYPE, class MAPPING>
620 {
621  contained_type* p1 = dynamic_cast<contained_type*>( p );
622  if ( p1 ) { // Normal case; object still fully intact
623  return this->erase( p1 );
624  } else if ( p ) {
625  const ObjectContainerBase* par = p->parent();
626  // The following should never occur: object is in a funny state,
627  // Because the parent was explicitly set to NULL in the
628  // KeyeObject destructor.
629  // - It cannot be a KeyedObject: It would not have a parent
630  // - Still the parent is present: We are not in the destructor
631  // of KeyedObject
632  if ( par ) {
634  }
635  return m_cont.erase( 0, p ) == 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_NOT_FOUND;
636  }
637  return (long)Containers::OBJ_NOT_FOUND;
638 }
639 
640 template <class DATATYPE, class MAPPING>
641 inline void KeyedContainer<DATATYPE, MAPPING>::erase( iterator start_pos, iterator stop_pos, bool use_tmp )
642 {
643  bool is_start = start_pos == m_sequential.begin();
644  bool is_stop = stop_pos == m_sequential.end();
645  if ( is_start && is_stop ) {
646  // Nothing special. Taken care of by Keyed object manager
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
658  std::vector<void*>::iterator i1 = v->begin() + std::distance( m_sequential.begin(), start_pos );
659  std::vector<void*>::iterator i2 = v->begin() + std::distance( m_sequential.begin(), stop_pos );
660  m_cont.erase( i1, i2 );
661 }
662 
663 #undef FORCE_INLINE
664 #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
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:35
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
Object not present in the container.
Definition: KeyedTraits.h:24
ObjectContainerBase * m_obj
template class KeyedContainer, KeyedContainer.h
STL namespace.
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 inserted into the container.
Definition: KeyedTraits.h:27
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.
constexpr auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
KeyedContainer< DATATYPE, MAPPING > * m_obj
GAUDI_API void cannotInsertToContainer()
Function to be called to indicate that an object cannot be inserted to the container.
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:51
const_iterator end() const
Retrieve terminating const iterator.
seq_type::value_type value_type
Sequential access: definition of type stored in sequential container.
Object was removed, but not deleted.
Definition: KeyedTraits.h:26
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
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
T insert(T...args)
~KeyedContainer() override
Destructor.
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.
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:253
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.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
T for_each(T...args)
#define GAUDI_API
Definition: Kernel.h:104
Object was removed from the container and deleted.
Definition: KeyedTraits.h:25
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)