The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
KeyedContainer.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 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#pragma once
12
16#include <algorithm>
17#include <iterator>
18
19namespace GaudiDict {
20 template <class T>
22}
23
60template <class DATATYPE, class MAPPING = Containers::HashMap>
62 friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
63
64public:
66 typedef DATATYPE contained_type;
68 typedef MAPPING container_type;
69
76
77 typedef typename std::vector<contained_type*> seq_type;
79 typedef typename contained_type::key_type key_type;
81 typedef typename seq_type::value_type value_type;
83 typedef typename seq_type::reference reference;
85 typedef typename seq_type::const_reference const_reference;
87 typedef typename seq_type::iterator iterator;
89 typedef typename seq_type::const_iterator const_iterator;
91 typedef typename seq_type::reverse_iterator reverse_iterator;
95 typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
97private:
102
106
112
114#ifdef CHECK_KEYED_CONTAINER
115 value_type i_object( const key_type& k ) const {
116 if ( 0 == m_cont.isDirect() ) {
117 if ( traits::checkBounds( m_random, k ) ) {
118 value_type p = *( m_random->begin() + traits::hash( k ) );
119 if ( traits::checkKey( p, k ) ) { return p; }
120 }
121 return 0;
122 }
123 value_type p = value_type( m_cont.object( traits::hash( k ) ) );
124 return traits::checkKey( p, k ) ? p : 0;
125 }
126#else
127 inline value_type i_object( const key_type& k ) const {
128 return 0 == m_cont.isDirect() ? value_type( *( m_random->begin() + traits::hash( k ) ) )
129 : value_type( m_cont.object( traits::hash( k ) ) );
130 }
131#endif
133 long i_erase( const_reference v, const key_type& k ) {
134 value_type p = value_type( m_cont.erase( traits::hash( k ), v ) );
135 if ( p ) {
136 if ( p->parent() == this ) { p->setParent( 0 ); }
137 }
138 return traits::release( p ) <= 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_DELETED;
139 }
140
150
156 const ObjectContainerBase* par = p->parent();
157 if ( par == m_obj ) { p->setParent( 0 ); }
158 traits::release( p );
159 }
160 };
161
162
163public:
167
169 // avoid problems with strict-aliasing rules
170 seq_type** rptr = &m_random;
171 seq_type* sptr = &m_sequential;
172 m_cont.setup( (void*)sptr, (void**)rptr );
173 }
175 : ObjectContainerBase( std::move( other ) )
176 , m_cont( std::move( other.m_cont ) )
177 , m_sequential( std::move( other.m_sequential ) ) {
178 m_cont.setup( (void*)&m_sequential, (void**)&m_random );
179 std::for_each( begin(), end(), [this]( ContainedObject* obj ) { obj->setParent( this ); } );
180
181 other.m_cont.setup( (void*)&other.m_sequential, (void**)&other.m_random );
182 }
183 KeyedContainer( const KeyedContainer& ) = delete;
185 ~KeyedContainer() override;
187
193
194 const CLID& clID() const override { return this->classID(); }
196 static const CLID& classID() {
197 static CLID clid = contained_type::classID() + container_type::classID();
198 return clid;
199 }
200
201
218
219 size_type numberOfObjects() const override { return m_sequential.size(); }
231 long add( ContainedObject* pObject ) override;
232
245 long remove( ContainedObject* pObject ) override;
246
250 ContainedObject* containedObject( long key_value ) override { return i_object( traits::makeKey( key_value ) ); }
251 ContainedObject const* containedObject( long key_value ) const override {
252 return i_object( traits::makeKey( key_value ) );
253 }
254
257 long index( const ContainedObject* p ) const override;
263 virtual size_type containedObjects( std::vector<ContainedObject*>& v ) const;
265
271
272 size_type size() const { return m_sequential.size(); }
274 bool empty() const { return m_sequential.empty(); }
276 void reserve( size_type value ) { m_cont.reserve( value ); }
278 void clear() { erase( begin(), end() ); }
284 virtual const std::vector<const ContainedObject*>* containedObjects() const;
289 StatusCode update() override;
291
305
306 iterator begin() { return m_sequential.begin(); }
308 const_iterator begin() const { return m_sequential.begin(); }
310 iterator end() { return m_sequential.end(); }
312 const_iterator end() const { return m_sequential.end(); }
314 reverse_iterator rbegin() { return m_sequential.rbegin(); }
316 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
318 reverse_iterator rend() { return m_sequential.rend(); }
320 const_reverse_iterator rend() const { return m_sequential.rend(); }
322
332
340 value_type object( const key_type& kval ) const { return i_object( kval ); }
341
351 value_type operator()( const key_type& kval ) const { return i_object( kval ); }
353
360
376 long erase( const key_type& kval ) { return i_erase( 0, kval ); }
377
398 long erase( const value_type val ) { return ( val ) ? i_erase( val, val->key() ) : (long)Containers::OBJ_NOT_FOUND; }
399
420 long erase( iterator pos ) { return erase( *pos ); }
421
430 void erase( iterator pos_start, iterator pos_stop, bool use_temp = false );
431
450 const key_type& insert( const value_type val, const key_type& kval );
451
452 const key_type& insert( std::unique_ptr<contained_type> val, const key_type& kval ) {
453 return insert( val.release(), kval );
454 }
455
477 const key_type& insert( const value_type val );
478
479 const key_type& insert( std::unique_ptr<contained_type> val ) { return insert( val.release() ); }
481};
482
489
490// Destructor
491template <class DATATYPE, class MAPPING>
496
497// Configure direct access
498template <class DATATYPE, class MAPPING>
500 int count = 0;
501 m_cont.clearDirect();
502 for ( typename seq_type::value_type v : m_sequential ) {
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.
519template <class DATATYPE, class MAPPING>
520inline const std::vector<const ContainedObject*>* KeyedContainer<DATATYPE, MAPPING>::containedObjects() const {
521 return reinterpret_cast<const std::vector<const ContainedObject*>*>( ( 0 == m_cont.isDirect() ) ? m_random
522 : &m_sequential );
523}
524
525template <class DATATYPE, class MAPPING>
528 if ( val ) {
529 long k0 = traits::hash( kval );
530 if ( !val->hasKey() || ( traits::hash( val->key() ) == k0 ) ) {
531 if ( m_cont.insert( this, val, val, k0 ) == Containers::OBJ_INSERTED ) {
532 if ( !val->hasKey() ) traits::setKey( val, kval );
533 traits::addRef( val );
534 return val->key();
535 }
536 }
537 }
538 // Cannot insert object...indicate bad object insertion...
540 return val->key();
541}
542
543// Insert object
544template <class DATATYPE, class MAPPING> // inline
547 if ( 0 != val ) {
548 if ( val->hasKey() ) {
549 if ( m_cont.insert( this, val, val, traits::hash( val->key() ) ) == Containers::OBJ_INSERTED ) {
550 traits::addRef( val );
551 return val->key();
552 }
553 }
554 long k0;
555 if ( m_cont.insert( this, val, val, &k0 ) == Containers::OBJ_INSERTED ) {
556 traits::setKey( val, traits::makeKey( k0 ) );
557 traits::addRef( val );
558 return val->key();
559 }
560 }
561 // Cannot insert object...indicate bad object insertion...
563 return val->key();
564}
565
566template <class DATATYPE, class MAPPING>
568 const contained_type* ptr = dynamic_cast<const contained_type*>( p );
569 if ( ptr ) return traits::identifier( ptr->key() );
570 return -1;
571}
572
573// Retrieve the full content of the object container.
574template <class DATATYPE, class MAPPING>
576KeyedContainer<DATATYPE, MAPPING>::containedObjects( std::vector<ContainedObject*>& vec ) const {
577 vec.clear();
578 vec.reserve( size() );
579 for ( typename seq_type::value_type v : m_sequential ) {
580 ContainedObject* p = const_cast<typename seq_type::value_type>( v );
581 vec.push_back( p );
582 }
583 return vec.size();
584}
585
586// ObjectContainerBase overload: Add an object to the container.
587template <class DATATYPE, class MAPPING>
589 return traits::identifier( insert( dynamic_cast<typename seq_type::value_type>( pObject ) ) );
590}
591
592// ObjectContainerBase overload: Remove an object from the container.
593template <class DATATYPE, class MAPPING>
595 contained_type* p1 = dynamic_cast<contained_type*>( p );
596 if ( p1 ) { // Normal case; object still fully intact
597 return this->erase( p1 );
598 } else if ( p ) {
599 const ObjectContainerBase* par = p->parent();
600 // The following should never occur: object is in a funny state,
601 // Because the parent was explicitly set to NULL in the
602 // KeyeObject destructor.
603 // - It cannot be a KeyedObject: It would not have a parent
604 // - Still the parent is present: We are not in the destructor
605 // of KeyedObject
607 return m_cont.erase( 0, p ) == 0 ? (long)Containers::OBJ_ERASED : (long)Containers::OBJ_NOT_FOUND;
608 }
609 return (long)Containers::OBJ_NOT_FOUND;
610}
611
612template <class DATATYPE, class MAPPING>
613inline void KeyedContainer<DATATYPE, MAPPING>::erase( iterator start_pos, iterator stop_pos, bool use_tmp ) {
614 bool is_start = start_pos == m_sequential.begin();
615 bool is_stop = stop_pos == m_sequential.end();
616 if ( is_start && is_stop ) {
617 // Nothing special. Taken care of by Keyed object manager
618 } else if ( is_start || is_stop || use_tmp ) {
619 std::vector<DATATYPE*> tmp( m_sequential.begin(), start_pos );
620 tmp.insert( tmp.end(), stop_pos, m_sequential.end() );
621 std::for_each( tmp.begin(), tmp.end(), traits::addRef );
622 this->erase( m_sequential.begin(), m_sequential.end() );
623 std::for_each( tmp.begin(), tmp.end(), _InsertRelease( this ) );
624 return;
625 }
626 std::for_each( start_pos, stop_pos, _RemoveRelease( this ) );
627 seq_type* sptr = &m_sequential; // avoid problems with strict-aliasing rules
628 std::vector<void*>* v = reinterpret_cast<std::vector<void*>*>( sptr );
629 std::vector<void*>::iterator i1 = v->begin() + std::distance( m_sequential.begin(), start_pos );
630 std::vector<void*>::iterator i2 = v->begin() + std::distance( m_sequential.begin(), stop_pos );
631 m_cont.erase( i1, i2 ); // cppcheck-suppress iterators1
632}
unsigned int CLID
Class ID definition.
Definition ClassID.h:16
#define GAUDI_API
Definition Kernel.h:49
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
void setParent(ObjectContainerBase *value)
Update parent member.
const ObjectContainerBase * parent() const
Access to parent object.
static const CLID & classID()
Retrieve reference to class definition structure (static access)
MAPPING container_type
Definition of the implementing container type.
const_iterator end() const
Retrieve terminating const iterator.
const_reverse_iterator rend() const
const reverse_iterator pointing to the end of the reversed container
void clear()
Clear the entire content and erase the objects from the container.
long erase(iterator pos)
Remove/erase object (identified by iterator) from the container.
long remove(ContainedObject *pObject) override
ObjectContainerBase overload: Remove an object from the container.
long add(ContainedObject *pObject) override
ObjectContainerBase overload: Add an object to the container.
bool empty() const
For consistency with STL: check if container is empty.
long erase(const value_type val)
Remove/erase object (identified by pointer value) from the container.
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.
size_type numberOfObjects() const override
ObjectContainerBase overload: Number of objects in the container.
static const CLID & classID()
Retrieve class ID.
const_reverse_iterator rbegin() const
const reverse_iterator returns the beginning of the reversed container
ContainedObject * containedObject(long key_value) override
ObjectContainerBase overload: Retrieve the object by reference given the long integer representation ...
void erase(iterator pos_start, iterator pos_stop, bool use_temp=false)
Remove/erase objects by iterator range.
size_type size() const
Number of objects in the container.
const key_type & insert(std::unique_ptr< contained_type > val, const key_type &kval)
const key_type & insert(const value_type val, const key_type &kval)
Insert entry to the container with a valid key.
seq_type::const_reverse_iterator const_reverse_iterator
Sequential access: const reverse iterator type used in sequential container.
const key_type & insert(const value_type val)
Insert entry to the container with automatic key assignment.
long index(const ContainedObject *p) const override
ObjectContainerBase overload: Retrieve the full long integer representation of the object's key from ...
DATATYPE contained_type
Definition of the contained object type.
Containers::traits< container_type, contained_type > traits
Traits class definition.
~KeyedContainer() override
Destructor.
KeyedContainer(const KeyedContainer &)=delete
KeyedContainer(void)
Standard Constructor.
virtual size_type containedObjects(std::vector< ContainedObject * > &v) const
Retrieve the full content of the object container.
seq_type::reference reference
Sequential access: reference type used in sequential container.
reverse_iterator rbegin()
reverse_iterator returns the beginning of the reversed container
const CLID & clID() const override
Retrieve class ID.
long i_erase(const_reference v, const key_type &k)
Internal function to erase an object from the container.
seq_type::const_reference const_reference
Sequential access: const reference type used in sequential container.
ContainedObject const * containedObject(long key_value) const override
Pointer to an object of a given distance.
seq_type::iterator iterator
Sequential access: iterator type used in sequential container.
const_iterator begin() const
Retrieve start const iterator.
KeyedContainer(KeyedContainer &&other)
StatusCode update() override
Reconfigure direct access to elements (Needed by POOL data loading) This function reuses the "update"...
seq_type::reverse_iterator reverse_iterator
Sequential access: reverse iterator type used in sequential container.
contained_type::key_type key_type
Definition of the key type: re-use definition of contained type.
value_type object(const key_type &kval) const
Object access by key.
value_type i_object(const key_type &k) const
virtual const std::vector< const ContainedObject * > * containedObjects() const
Retrieve the full content of the object container by reference.
reverse_iterator rend()
reverse_iterator pointing to the end of the reversed container
const key_type & insert(std::unique_ptr< contained_type > val)
seq_type::const_iterator const_iterator
Sequential access: const iterator type used in sequential container.
std::vector< contained_type * > seq_type
General container specific type definitions.
void reserve(size_type value)
Reserve place for "value" objects in the container.
ObjectContainerBase()=default
Constructor.
size_t size_type
size_type, to conform the STL container interface
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
constexpr static const auto SUCCESS
Definition StatusCode.h:99
@ OBJ_DELETED
Object was removed from the container and deleted.
Definition KeyedTraits.h:31
@ OBJ_INSERTED
Object was inserted into the container.
Definition KeyedTraits.h:33
@ OBJ_ERASED
Object was removed, but not deleted.
Definition KeyedTraits.h:32
@ OBJ_NOT_FOUND
Object not present in the container.
Definition KeyedTraits.h:30
GAUDI_API void cannotInsertToContainer()
Function to be called to indicate that an object cannot be inserted to the container.
GAUDI_API void invalidContainerOperation()
Function to be called to indicate that an operation should be performed on the container or it's cont...
STL namespace.
static long identifier(const key_type &k)
Full unhashed key identifier.
Definition KeyedTraits.h:87
static bool checkKey(obj_type *v, const key_type &k)
Check the validity of the object's key.
Definition KeyedTraits.h:98
static void setKey(obj_type *v, const key_type &k)
Set object key when inserted into the container.
Definition KeyedTraits.h:91
static long release(obj_type *v)
Release reference to object.
static long hash(const key_type &key_value)
Hash function for this key.
Definition KeyedTraits.h:89
static key_type makeKey(long k)
Create key from its full integer representation.
Definition KeyedTraits.h:84
static long addRef(obj_type *v)
Add reference counter to object when inserted into the container.
Container traits class.
static bool checkBounds(const std::vector< contained_type * > *cnt, const typename contained_type::key_type &k)
Internal functor for insertion of objects.
_InsertRelease(KeyedContainer< DATATYPE, MAPPING > *p)
KeyedContainer< DATATYPE, MAPPING > * m_obj
Internal functor for insertion of objects.
_RemoveRelease(ObjectContainerBase *p)
ObjectContainerBase * m_obj