The Gaudi Framework  v33r1 (b1225454)
KeyedContainer.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H
12 #define GAUDIKERNEL_KEYEDCONTAINER_H
13 
14 // Include files
15 #include <algorithm>
16 #include <iterator>
17 
18 namespace GaudiDict {
19  template <class T>
21 }
22 
23 // Framework include files
27 
28 // Forward declarations
29 // template <class T, class M> class KeyedContainer;
30 
31 #ifdef WIN32
32 # define FORCE_INLINE __forceinline
33 #else
34 # define FORCE_INLINE inline
35 #endif
36 
73 template <class DATATYPE, class MAPPING = Containers::HashMap>
75  friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
76 
77 public:
79  typedef DATATYPE contained_type;
81  typedef MAPPING container_type;
82 
89  typedef typename std::vector<contained_type*> seq_type;
92  typedef typename contained_type::key_type key_type;
94  typedef typename seq_type::value_type value_type;
96  typedef typename seq_type::reference reference;
98  typedef typename seq_type::const_reference const_reference;
100  typedef typename seq_type::iterator iterator;
102  typedef typename seq_type::const_iterator const_iterator;
104  typedef typename seq_type::reverse_iterator reverse_iterator;
108  typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
110 private:
115 
119  container_type m_cont;
125 
127 #ifdef CHECK_KEYED_CONTAINER
128  value_type i_object( const key_type& k ) const {
129  if ( 0 == m_cont.isDirect() ) {
130  if ( traits::checkBounds( m_random, k ) ) {
131  value_type p = *( m_random->begin() + traits::hash( k ) );
132  if ( traits::checkKey( p, k ) ) { return p; }
133  }
134  return 0;
135  }
136  value_type p = value_type( m_cont.object( traits::hash( k ) ) );
137  return traits::checkKey( p, k ) ? p : 0;
138  }
139 #else
141  return 0 == m_cont.isDirect() ? value_type( *( m_random->begin() + traits::hash( k ) ) )
142  : value_type( m_cont.object( traits::hash( k ) ) );
143  }
144 #endif
145  long i_erase( const_reference v, const key_type& k ) {
147  value_type p = value_type( m_cont.erase( traits::hash( k ), v ) );
148  if ( p ) {
149  if ( p->parent() == this ) { p->setParent( 0 ); }
150  }
151  return traits::release( p ) <= 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_DELETED;
152  }
153 
155  struct _InsertRelease {
158  void operator()( value_type p ) {
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  const ObjectContainerBase* par = p->parent();
170  if ( par == m_obj ) { p->setParent( 0 ); }
171  traits::release( p );
172  }
173  };
175 
176 public:
180  KeyedContainer( void ) {
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  : ObjectContainerBase( std::move( other ) )
189  , m_cont( std::move( other.m_cont ) )
190  , m_sequential( std::move( other.m_sequential ) ) {
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 ) override { return i_object( traits::makeKey( key_value ) ); }
264  ContainedObject const* containedObject( long key_value ) const override {
265  return i_object( traits::makeKey( key_value ) );
266  }
270  long index( const ContainedObject* p ) const override;
276  virtual size_type containedObjects( std::vector<ContainedObject*>& v ) const;
278 
284  size_type size() const { return m_sequential.size(); }
287  bool empty() const { return m_sequential.empty(); }
289  void reserve( size_type value ) { m_cont.reserve( value ); }
291  void clear() { erase( begin(), end() ); }
297  virtual const std::vector<const ContainedObject*>* containedObjects() const;
302  StatusCode update() override;
304 
318  iterator begin() { return m_sequential.begin(); }
321  const_iterator begin() const { return m_sequential.begin(); }
323  iterator end() { return m_sequential.end(); }
325  const_iterator end() const { return m_sequential.end(); }
327  reverse_iterator rbegin() { return m_sequential.rbegin(); }
329  const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
331  reverse_iterator rend() { return m_sequential.rend(); }
333  const_reverse_iterator rend() const { return m_sequential.rend(); }
335 
353  value_type object( const key_type& kval ) const { return i_object( kval ); }
354 
364  value_type operator()( const key_type& kval ) const { return i_object( kval ); }
366 
389  long erase( const key_type& kval ) { return i_erase( 0, kval ); }
390 
411  long erase( const value_type val ) { return ( val ) ? i_erase( val, val->key() ) : (long)Containers::OBJ_NOT_FOUND; }
412 
433  long erase( iterator pos ) { return erase( *pos ); }
434 
443  void erase( iterator pos_start, iterator pos_stop, bool use_temp = false );
444 
463  const key_type& insert( const value_type val, const key_type& kval );
464 
486  const key_type& insert( const value_type val );
488 };
489 
497 // Destructor
498 template <class DATATYPE, class MAPPING>
500  clear();
501  m_cont.clear();
502 }
503 
504 // Configure direct access
505 template <class DATATYPE, class MAPPING>
507  int count = 0;
508  m_cont.clearDirect();
509  typename seq_type::iterator i = m_sequential.begin();
510  typename seq_type::iterator s = m_sequential.end();
511  for ( ; i != s; i++ ) {
512  typename seq_type::value_type v = *i;
513  if ( v ) {
514  if ( !v->hasKey() ) {
515  traits::setKey( v, v->key() );
516  traits::addRef( v );
517  }
518  long k0 = traits::hash( v->key() );
519  if ( m_cont.insertDirect( this, v, v, k0 ) == Containers::OBJ_INSERTED ) {}
520  } else {
521  ++count;
522  }
523  }
524  if ( count > 0 ) { Containers::cannotInsertToContainer(); }
525  return StatusCode::SUCCESS;
526 }
527 
528 // Retrieve the full content of the object container by reference.
529 template <class DATATYPE, class MAPPING>
531  return (const std::vector<const ContainedObject*>*)( ( 0 == m_cont.isDirect() ) ? m_random : &m_sequential );
532 }
533 
534 template <class DATATYPE, class MAPPING>
535 inline const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
537  if ( val ) {
538  long k0 = traits::hash( kval );
539  if ( !val->hasKey() || ( traits::hash( val->key() ) == k0 ) ) {
540  if ( m_cont.insert( this, val, val, k0 ) == Containers::OBJ_INSERTED ) {
541  if ( !val->hasKey() ) traits::setKey( val, kval );
542  traits::addRef( val );
543  return val->key();
544  }
545  }
546  }
547  // Cannot insert object...indicate bad object insertion...
549  return val->key();
550 }
551 
552 // Insert object
553 template <class DATATYPE, class MAPPING> // inline
556  if ( 0 != val ) {
557  if ( val->hasKey() ) {
558  if ( m_cont.insert( this, val, val, traits::hash( val->key() ) ) == Containers::OBJ_INSERTED ) {
559  traits::addRef( val );
560  return val->key();
561  }
562  }
563  long k0;
564  if ( m_cont.insert( this, val, val, &k0 ) == Containers::OBJ_INSERTED ) {
565  traits::setKey( val, traits::makeKey( k0 ) );
566  traits::addRef( val );
567  return val->key();
568  }
569  }
570  // Cannot insert object...indicate bad object insertion...
572  return val->key();
573 }
574 
575 template <class DATATYPE, class MAPPING>
577  const contained_type* ptr = dynamic_cast<const contained_type*>( p );
578  if ( ptr ) return traits::identifier( ptr->key() );
579  return -1;
580 }
581 
582 // Retrieve the full content of the object container.
583 template <class DATATYPE, class MAPPING>
586  typename seq_type::const_iterator i = m_sequential.begin();
587  typename seq_type::const_iterator s = m_sequential.end();
588  vec.clear();
589  vec.reserve( size() );
590  for ( ; i != s; i++ ) {
591  ContainedObject* p = const_cast<typename seq_type::value_type>( *i );
592  vec.push_back( p );
593  }
594  return vec.size();
595 }
596 
597 // ObjectContainerBase overload: Add an object to the container.
598 template <class DATATYPE, class MAPPING>
600  return traits::identifier( insert( dynamic_cast<typename seq_type::value_type>( pObject ) ) );
601 }
602 
603 // ObjectContainerBase overload: Remove an object from the container.
604 template <class DATATYPE, class MAPPING>
606  contained_type* p1 = dynamic_cast<contained_type*>( p );
607  if ( p1 ) { // Normal case; object still fully intact
608  return this->erase( p1 );
609  } else if ( p ) {
610  const ObjectContainerBase* par = p->parent();
611  // The following should never occur: object is in a funny state,
612  // Because the parent was explicitly set to NULL in the
613  // KeyeObject destructor.
614  // - It cannot be a KeyedObject: It would not have a parent
615  // - Still the parent is present: We are not in the destructor
616  // of KeyedObject
618  return m_cont.erase( 0, p ) == 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_NOT_FOUND;
619  }
620  return (long)Containers::OBJ_NOT_FOUND;
621 }
622 
623 template <class DATATYPE, class MAPPING>
624 inline void KeyedContainer<DATATYPE, MAPPING>::erase( iterator start_pos, iterator stop_pos, bool use_tmp ) {
625  bool is_start = start_pos == m_sequential.begin();
626  bool is_stop = stop_pos == m_sequential.end();
627  if ( is_start && is_stop ) {
628  // Nothing special. Taken care of by Keyed object manager
629  } else if ( is_start || is_stop || use_tmp ) {
630  std::vector<DATATYPE*> tmp( m_sequential.begin(), start_pos );
631  tmp.insert( tmp.end(), stop_pos, m_sequential.end() );
632  std::for_each( tmp.begin(), tmp.end(), traits::addRef );
633  this->erase( m_sequential.begin(), m_sequential.end() );
634  std::for_each( tmp.begin(), tmp.end(), _InsertRelease( this ) );
635  return;
636  }
637  std::for_each( start_pos, stop_pos, _RemoveRelease( this ) );
638  seq_type* sptr = &m_sequential; // avoid problems with strict-aliasing rules
640  std::vector<void*>::iterator i1 = v->begin() + std::distance( m_sequential.begin(), start_pos );
641  std::vector<void*>::iterator i2 = v->begin() + std::distance( m_sequential.begin(), stop_pos );
642  m_cont.erase( i1, i2 );
643 }
644 
645 #undef FORCE_INLINE
646 #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:75
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:44
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:69
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:33
ObjectContainerBase * m_obj
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
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:36
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:61
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:35
def end
Definition: IOTest.py:123
seq_type::const_iterator const_iterator
Sequential access: const iterator type used in sequential container.
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
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:66
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:328
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:81
Object was removed from the container and deleted.
Definition: KeyedTraits.h:34
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)