The Gaudi Framework  v32r2 (46d42edc)
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  template <class T>
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  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;
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 ) ) { return p; }
123  }
124  return 0;
125  }
126  value_type p = value_type( m_cont.object( traits::hash( k ) ) );
127  return traits::checkKey( p, k ) ? p : 0;
128  }
129 #else
131  return 0 == m_cont.isDirect() ? value_type( *( m_random->begin() + traits::hash( k ) ) )
132  : value_type( m_cont.object( traits::hash( k ) ) );
133  }
134 #endif
135  long i_erase( const_reference v, const key_type& k ) {
137  value_type p = value_type( m_cont.erase( traits::hash( k ), v ) );
138  if ( p ) {
139  if ( p->parent() == this ) { p->setParent( 0 ); }
140  }
141  return traits::release( p ) <= 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_DELETED;
142  }
143 
145  struct _InsertRelease {
148  void operator()( value_type p ) {
149  m_obj->insert( p );
150  traits::release( p );
151  }
152  };
153 
155  struct _RemoveRelease {
157  _RemoveRelease( ObjectContainerBase* p ) : m_obj( p ) {}
158  void operator()( value_type p ) {
159  const ObjectContainerBase* par = p->parent();
160  if ( par == m_obj ) { p->setParent( 0 ); }
161  traits::release( p );
162  }
163  };
165 
166 public:
170  KeyedContainer( void ) {
172  // avoid problems with strict-aliasing rules
173  seq_type** rptr = &m_random;
174  seq_type* sptr = &m_sequential;
175  m_cont.setup( (void*)sptr, (void**)rptr );
176  }
178  : ObjectContainerBase( std::move( other ) )
179  , m_cont( std::move( other.m_cont ) )
180  , m_sequential( std::move( other.m_sequential ) ) {
181  m_cont.setup( (void*)&m_sequential, (void**)&m_random );
182  std::for_each( begin(), end(), [this]( ContainedObject* obj ) { obj->setParent( this ); } );
183 
184  other.m_cont.setup( (void*)&other.m_sequential, (void**)&other.m_random );
185  }
186  KeyedContainer( const KeyedContainer& ) = delete;
188  ~KeyedContainer() override;
190 
196  const CLID& clID() const override { return this->classID(); }
199  static const CLID& classID() {
200  static CLID clid = contained_type::classID() + container_type::classID();
201  return clid;
202  }
204 
221  size_type numberOfObjects() const override { return m_sequential.size(); }
234  long add( ContainedObject* pObject ) override;
235 
248  long remove( ContainedObject* pObject ) override;
249 
253  ContainedObject* containedObject( long key_value ) override { return i_object( traits::makeKey( key_value ) ); }
254  ContainedObject const* containedObject( long key_value ) const override {
255  return i_object( traits::makeKey( key_value ) );
256  }
260  long index( const ContainedObject* p ) const override;
266  virtual size_type containedObjects( std::vector<ContainedObject*>& v ) const;
268 
274  size_type size() const { return m_sequential.size(); }
277  bool empty() const { return m_sequential.empty(); }
279  void reserve( size_type value ) { m_cont.reserve( value ); }
281  void clear() { erase( begin(), end() ); }
287  virtual const std::vector<const ContainedObject*>* containedObjects() const;
292  StatusCode update() override;
294 
308  iterator begin() { return m_sequential.begin(); }
311  const_iterator begin() const { return m_sequential.begin(); }
313  iterator end() { return m_sequential.end(); }
315  const_iterator end() const { return m_sequential.end(); }
317  reverse_iterator rbegin() { return m_sequential.rbegin(); }
319  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
321  reverse_iterator rend() { return m_sequential.rend(); }
323  const_reverse_iterator rend() const { return m_sequential.rend(); }
325 
343  value_type object( const key_type& kval ) const { return i_object( kval ); }
344 
354  value_type operator()( const key_type& kval ) const { return i_object( kval ); }
356 
379  long erase( const key_type& kval ) { return i_erase( 0, kval ); }
380 
401  long erase( const value_type val ) { return ( val ) ? i_erase( val, val->key() ) : (long)Containers::OBJ_NOT_FOUND; }
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 
487 // Destructor
488 template <class DATATYPE, class MAPPING>
490  clear();
491  m_cont.clear();
492 }
493 
494 // Configure direct access
495 template <class DATATYPE, class MAPPING>
497  int count = 0;
498  m_cont.clearDirect();
499  typename seq_type::iterator i = m_sequential.begin();
500  typename seq_type::iterator s = m_sequential.end();
501  for ( ; i != s; i++ ) {
502  typename seq_type::value_type v = *i;
503  if ( v ) {
504  if ( !v->hasKey() ) {
505  traits::setKey( v, v->key() );
506  traits::addRef( v );
507  }
508  long k0 = traits::hash( v->key() );
509  if ( m_cont.insertDirect( this, v, v, k0 ) == Containers::OBJ_INSERTED ) {}
510  } else {
511  ++count;
512  }
513  }
514  if ( count > 0 ) { Containers::cannotInsertToContainer(); }
515  return StatusCode::SUCCESS;
516 }
517 
518 // Retrieve the full content of the object container by reference.
519 template <class DATATYPE, class MAPPING>
521  return (const std::vector<const ContainedObject*>*)( ( 0 == m_cont.isDirect() ) ? m_random : &m_sequential );
522 }
523 
524 template <class DATATYPE, class MAPPING>
525 inline const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
527  if ( val ) {
528  long k0 = traits::hash( kval );
529  if ( !val->hasKey() || ( traits::hash( val->key() ) == k0 ) ) {
530  if ( m_cont.insert( this, val, val, k0 ) == Containers::OBJ_INSERTED ) {
531  if ( !val->hasKey() ) traits::setKey( val, kval );
532  traits::addRef( val );
533  return val->key();
534  }
535  }
536  }
537  // Cannot insert object...indicate bad object insertion...
539  return val->key();
540 }
541 
542 // Insert object
543 template <class DATATYPE, class MAPPING> // inline
546  if ( 0 != val ) {
547  if ( val->hasKey() ) {
548  if ( m_cont.insert( this, val, val, traits::hash( val->key() ) ) == Containers::OBJ_INSERTED ) {
549  traits::addRef( val );
550  return val->key();
551  }
552  }
553  long k0;
554  if ( m_cont.insert( this, val, val, &k0 ) == Containers::OBJ_INSERTED ) {
555  traits::setKey( val, traits::makeKey( k0 ) );
556  traits::addRef( val );
557  return val->key();
558  }
559  }
560  // Cannot insert object...indicate bad object insertion...
562  return val->key();
563 }
564 
565 template <class DATATYPE, class MAPPING>
567  const contained_type* ptr = dynamic_cast<const contained_type*>( p );
568  if ( ptr ) return traits::identifier( ptr->key() );
569  return -1;
570 }
571 
572 // Retrieve the full content of the object container.
573 template <class DATATYPE, class MAPPING>
576  typename seq_type::const_iterator i = m_sequential.begin();
577  typename seq_type::const_iterator s = m_sequential.end();
578  vec.clear();
579  vec.reserve( size() );
580  for ( ; i != s; i++ ) {
581  ContainedObject* p = const_cast<typename seq_type::value_type>( *i );
582  vec.push_back( p );
583  }
584  return vec.size();
585 }
586 
587 // ObjectContainerBase overload: Add an object to the container.
588 template <class DATATYPE, class MAPPING>
590  return traits::identifier( insert( dynamic_cast<typename seq_type::value_type>( pObject ) ) );
591 }
592 
593 // ObjectContainerBase overload: Remove an object from the container.
594 template <class DATATYPE, class MAPPING>
596  contained_type* p1 = dynamic_cast<contained_type*>( p );
597  if ( p1 ) { // Normal case; object still fully intact
598  return this->erase( p1 );
599  } else if ( p ) {
600  const ObjectContainerBase* par = p->parent();
601  // The following should never occur: object is in a funny state,
602  // Because the parent was explicitly set to NULL in the
603  // KeyeObject destructor.
604  // - It cannot be a KeyedObject: It would not have a parent
605  // - Still the parent is present: We are not in the destructor
606  // of KeyedObject
608  return m_cont.erase( 0, p ) == 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_NOT_FOUND;
609  }
610  return (long)Containers::OBJ_NOT_FOUND;
611 }
612 
613 template <class DATATYPE, class MAPPING>
614 inline void KeyedContainer<DATATYPE, MAPPING>::erase( iterator start_pos, iterator stop_pos, bool use_tmp ) {
615  bool is_start = start_pos == m_sequential.begin();
616  bool is_stop = stop_pos == m_sequential.end();
617  if ( is_start && is_stop ) {
618  // Nothing special. Taken care of by Keyed object manager
619  } else if ( is_start || is_stop || use_tmp ) {
620  std::vector<DATATYPE*> tmp( m_sequential.begin(), start_pos );
621  tmp.insert( tmp.end(), stop_pos, m_sequential.end() );
622  std::for_each( tmp.begin(), tmp.end(), traits::addRef );
623  this->erase( m_sequential.begin(), m_sequential.end() );
624  std::for_each( tmp.begin(), tmp.end(), _InsertRelease( this ) );
625  return;
626  }
627  std::for_each( start_pos, stop_pos, _RemoveRelease( this ) );
628  seq_type* sptr = &m_sequential; // avoid problems with strict-aliasing rules
630  std::vector<void*>::iterator i1 = v->begin() + std::distance( m_sequential.begin(), start_pos );
631  std::vector<void*>::iterator i2 = v->begin() + std::distance( m_sequential.begin(), stop_pos );
632  m_cont.erase( i1, i2 );
633 }
634 
635 #undef FORCE_INLINE
636 #endif // GAUDIKERNEL_KEYEDCONTAINER_H
constexpr auto size(const T &, Args &&...) noexcept
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:65
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:34
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.
T distance(T... args)
static const CLID & classID()
Retrieve reference to class definition structure (static access)
Definition: DataObject.cpp:59
const_reverse_iterator rend() const
const reverse_iterator pointing to the end of the reversed container
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
ContainedObject const * containedObject(long key_value) const override
Pointer to an object of a given distance.
T rend(T... args)
FORCE_INLINE value_type i_object(const key_type &k) const
Internal function to access objects within the container.
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.
virtual size_type numberOfObjects() const =0
Number of objects in the container.
ContainedObject * containedObject(long key_value) override
ObjectContainerBase overload: Retrieve the object by reference given the long integer representation ...
Object not present in the container.
Definition: KeyedTraits.h:23
ObjectContainerBase * m_obj
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
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.
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.
const_reverse_iterator rbegin() const
const reverse_iterator returns the beginning of the reversed container
Object was inserted into the container.
Definition: KeyedTraits.h:26
const key_type & insert(const value_type val, const key_type &kval)
Insert entry to the container with a valid key.
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_iterator begin() const
Retrieve start const iterator.
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's cont...
KeyedContainer(KeyedContainer &&other)
virtual const std::vector< const ContainedObject * > * containedObjects() const
Retrieve the full content of the object container by reference.
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:50
value_type operator()(const key_type &kval) const
STL algorithms support for object access.
seq_type::value_type value_type
Sequential access: definition of type stored in sequential container.
Object was removed, but not deleted.
Definition: KeyedTraits.h:25
def end
Definition: IOTest.py:113
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.
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
T size(T... args)
value_type object(const key_type &kval) const
Object access by key.
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:56
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)
bool empty() const
For consistency with STL: check if container is empty.
iterator end()
Retrieve terminating iterator.
constexpr struct ranges::Gaudi::Functional::details::insert_t insert
virtual long index(const ContainedObject *obj) const =0
Distance of a given object from the beginning of its container.
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:318
virtual long remove(ContainedObject *value)=0
Release object from the container (the pointer will be removed from the container,...
const ObjectContainerBase * parent() const
Access to parent object.
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)
long index(const ContainedObject *p) const override
ObjectContainerBase overload: Retrieve the full long integer representation of the object's key from ...
T for_each(T... args)
#define GAUDI_API
Definition: Kernel.h:71
Object was removed from the container and deleted.
Definition: KeyedTraits.h:24
const_iterator end() const
Retrieve terminating const iterator.
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)