ATLAS Offline Software
Loading...
Searching...
No Matches
AuxContainerBase.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6
7// EDM include(s):
11
12// Local include(s):
16
17#ifndef XAOD_STANDALONE
18# include "GaudiKernel/ThreadLocalContext.h"
20#endif // not XAOD_STANDALONE
21
24
25// System include(s):
26#include <iostream> //std::cout
27#include <memory_resource>
28
29using namespace std;
30
31namespace xAOD {
32
33 AuxContainerBase::AuxContainerBase( bool allowDynamicVars )
34 : AuxContainerBase( nullptr, allowDynamicVars ) {
35 }
36
38 bool allowDynamicVars )
39 : SG::IAuxStore(),
40 m_auxids(), m_vecs(), m_store( nullptr ), m_storeIO( nullptr ),
41 m_ownsStore( true ),
42 m_locked( false ),
43 m_name( "UNKNOWN" ),
44 m_memResource( memResource ){
45
46 if( allowDynamicVars ) {
48 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
49 }
50 }
51
61 : SG::IAuxStore(),
62 m_auxids(), m_vecs(), m_store( nullptr ), m_storeIO( nullptr ),
63 m_ownsStore( true ),
64 m_locked( false ),
65 m_memResource( parent.m_memResource )
66 {
67 // Keep the source unmutable during copy
68 guard_t guard( parent.m_mutex );
69 m_name = parent.m_name;
70
71 // Unfortunately the dynamic variables can not be copied this easily...
72 if( parent.m_store ) {
73 m_ownsStore = false;
74 // cppcheck-suppress copyCtorPointerCopying
75 m_store = parent.m_store;
76 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
77 m_auxids = m_store->getAuxIDs();
78 }
79 }
80
87 std::pmr::memory_resource* memResource )
88 : SG::IAuxStore(),
89 m_auxids(), m_vecs(),
90 m_store( store ),
91 m_storeIO( nullptr ), m_ownsStore( false ),
92 m_locked( false),
93 m_name( "UNKNOWN" ),
94 m_memResource( memResource ){
95
96 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
97 if( m_store ) {
98 m_auxids = m_store->getAuxIDs();
99 }
100 }
101
103
104 std::vector< SG::IAuxTypeVector* >::iterator itr = m_vecs.begin();
105 std::vector< SG::IAuxTypeVector* >::iterator end = m_vecs.end();
106 for( ; itr != end; ++itr ) {
107 if( ! *itr ) continue;
108 delete *itr;
109 }
110
111 if( m_store && m_ownsStore ) delete m_store;
112 }
113
122
123 // Protect against self-assignment:
124 if( this == &rhs ) return *this;
125
126 // Keep the objects locked during copy
127 std::scoped_lock lck{m_mutex, rhs.m_mutex};
128
129 // Clean up after the old dynamic store:
130 if( m_store && m_ownsStore ) {
131 m_auxids -= m_store->getAuxIDs();
132 delete m_store;
133 }
134 m_store = nullptr;
135 m_storeIO = nullptr;
136 m_ownsStore = true;
137
138 // Take posession of the new dynamic store:
139 if( rhs.m_store ) {
140 m_store = rhs.m_store;
141 m_ownsStore = false;
142 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
143 m_auxids.insert (m_store->getAuxIDs());
144 }
145
146 m_name = rhs.m_name;
147
148 return *this;
149 }
150
152 //
153 // Implementation of the SG::IAuxStoreHolder functions
154 //
155
160
161 std::pmr::memory_resource* AuxContainerBase::memResource()
162 {
163 const std::pmr::memory_resource* cptr = m_memResource.get();
164 std::pmr::memory_resource* ptr ATLAS_THREAD_SAFE = const_cast<std::pmr::memory_resource*>( cptr );
165 if( !ptr ) {
166#ifndef XAOD_STANDALONE
167 const EventContext& ctx = Gaudi::Hive::currentContext();
168 if( Atlas::hasExtendedEventContext( ctx ) ) {
169 ptr = Atlas::getExtendedEventContext( ctx ).memResource();
170 }
171 if( !ptr )
172#endif
173 {
174 ptr = std::pmr::get_default_resource();
175 }
176 if( ptr ) {
177 m_memResource.set( ptr );
178 }
179 }
180 return ptr;
181 }
182
184 {
185 return m_store;
186 }
187
198
199 // Guard against multi-threaded execution:
200 guard_t guard( m_mutex );
201
202 // Check that no funny business is going on:
203 if( m_store == store ) return;
204
205 // Clean up the current store object:
206 if( m_store && m_ownsStore ) {
207 m_auxids -= m_store->getAuxIDs();
208 delete m_store;
209 }
210 m_store = nullptr;
211 m_storeIO = nullptr;
212
213 // Take posession of the new object:
214 m_store = store;
215 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
216 m_ownsStore = true;
217 if( m_store ) {
218 m_auxids.insert (m_store->getAuxIDs());
219 }
220
221 return;
222 }
223
224 //
226
228 //
229 // Implementation of the SG::IConstAuxStore functions
230 //
231
232 const void* AuxContainerBase::getData( auxid_t auxid ) const {
233
234 const SG::IAuxTypeVector* v = getVector( auxid );
235 if( v ) {
236 return v->toPtr();
237 }
238 return nullptr;
239 }
240
242
243 // Guard against multi-threaded execution:
244 guard_t guard( m_mutex );
245
246 if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ) {
247 if( m_store ) {
248 const SG::IAuxTypeVector* result = m_store->getVector( auxid );
249 if( result ) {
250 auxid_set_t& auxids_nc ATLAS_THREAD_SAFE =
251 const_cast<auxid_set_t&> (m_auxids);
252 auxids_nc.insert( auxid );
254 auxid_t linked_id = r.linkedVariable( auxid );
255 if (linked_id != SG::null_auxid) {
256 auxids_nc.insert( linked_id );
257 }
258 }
259 return result;
260 } else {
261 std::cout << "ERROR xAOD::AuxContainerBase::getData "
262 << "Unknown variable ("
264 << ") requested" << std::endl;
265 return nullptr;
266 }
267 }
268
269 // Update the statistics for this variable. The dynamic store registers
270 // its own variable accesses.
272
273 return m_vecs[ auxid ];
274 }
275
278
279 // Return the full list of IDs:
280 return getWritableAuxIDs();
281 }
282
285
286 if( m_store ) {
287 return m_store->getDecorIDs();
288 }
289 static const auxid_set_t empty;
290 return empty;
291 }
292
294 {
295 guard_t guard( m_mutex );
296 if (m_store) {
297 return m_store->isDecoration (auxid);
298 }
299 return false;
300 }
301
303 size_t capacity ) {
304 {
305 // Guard against multi-threaded execution:
306 guard_t guard( m_mutex );
307
308 // Check if we have it as a static variable:
309 if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ) {
310 // If not, but we have a dynamic store, push it in there:
311 if( m_store ) {
312 void* result = m_store->getDecoration( auxid, size, capacity );
313 if( result ) {
314 m_auxids.insert( auxid );
316 auxid_t linked_id = r.linkedVariable( auxid );
317 if (linked_id != SG::null_auxid) {
318 m_auxids.insert( linked_id );
319 }
320 }
321 return result;
322 }
323 // If we don't have a dynamic store, complain:
324 else {
325 std::cout << "ERROR xAOD::AuxContainerBase::getDecoration "
326 << "Can't provide variable "
328 << std::endl;
329 return nullptr;
330 }
331 }
332
333 // If the container is locked, static variables can't be accessed this
334 // way:
335 if( m_locked ) {
336 throw SG::ExcStoreLocked( auxid );
337 }
338 }
339
340 // If the container is not locked, then fall back on the normal accessor
341 // function:
342 return getData( auxid, size, capacity );
343 }
344
346
347 // Guard against multi-threaded execution:
348 guard_t guard( m_mutex );
349
350 // Lock the object and its dynamic store:
351 m_locked = true;
352 if( m_store ) {
353 m_store->lock();
354 }
355
356 return;
357 }
358
360
361 // Guard against multi-threaded execution:
362 guard_t guard( m_mutex );
363
364 // Clear the decorations from the dynamic store:
365 bool anycleared = false;
366 if( m_store ) {
367 anycleared = m_store->clearDecorations();
368 }
369 // Early exit if there were no decorations.
370 if (!anycleared) return false;
371
372 // Construct the list of managed auxiliary variables from scratch after
373 // the cleanup:
374 auxid_set_t ids;
375 for( auxid_t auxid = 0; auxid < m_vecs.size(); ++auxid ) {
376 if( m_vecs[ auxid ] ) {
377 ids.insert( auxid );
378 }
379 }
380 if( m_store ) {
381 ids.insert (m_store->getAuxIDs());
382 }
383 m_auxids = std::move(ids);
384
385 return true;
386 }
387
390 {
391 guard_t guard (m_mutex);
392 if (m_store) {
393 m_store->lockDecoration (auxid);
394 }
395 }
396
397
399 {
401 auxid_t linked_id = r.linkedVariable( auxid );
402 if (linked_id != SG::null_auxid) {
403 guard_t guard( m_mutex );
404 if (linked_id < m_vecs.size() && m_vecs[ linked_id ]) {
405 return m_vecs[ linked_id ];
406 }
407 if (m_store) {
408 return CxxUtils::as_const_ptr(m_store)->linkedVector( auxid );
409 }
410 }
411 return nullptr;
412 }
413
414
416 {
418 auxid_t linked_id = r.linkedVariable( auxid );
419 if (linked_id != SG::null_auxid) {
420 guard_t guard( m_mutex );
421 if (linked_id < m_vecs.size() && m_vecs[ linked_id ]) {
422 return m_vecs[ linked_id ];
423 }
424 if (m_store) {
425 return m_store->linkedVector( auxid );
426 }
427 }
428 return nullptr;
429 }
430
431
432 size_t AuxContainerBase::size() const {
433
434 // Guard against multi-threaded execution:
435 guard_t guard (m_mutex);
436
437 // Try to find a variable:
438 for (SG::auxid_t i : m_auxids) {
439 if( ( i < m_vecs.size() ) && m_vecs[ i ] && !m_vecs[ i ]->isLinked()) {
440 size_t sz = m_vecs[ i ]->size();
441 if( sz > 0 ) {
442 return sz;
443 }
444 }
445 }
446
447 // If we didn't find any, let's ask the dynamic store:
448 if( m_store ) {
449 return m_store->size();
450 }
451
452 // If we don't have any variables, then the size must be null:
453 return 0;
454 }
455
456 //
458
460 //
461 // Implementation of the SG::IAuxStore functions
462 //
463
465 size_t capacity ) {
466
467 // Guard against multi-threaded execution:
468 guard_t guard( m_mutex );
469
470 if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ) {
471
472 if( m_store ) {
473 void* result = m_store->getData( auxid, size, capacity );
474 if( result ) {
475 m_auxids.insert( auxid );
477 auxid_t linked_id = r.linkedVariable( auxid );
478 if (linked_id != SG::null_auxid) {
479 m_auxids.insert( linked_id );
480 }
481 }
482 return result;
483 } else {
484 std::cout << "ERROR xAOD::AuxContainerBase::getData "
485 << "Unknown variable ("
487 << ") requested" << std::endl;
488 return nullptr;
489 }
490 }
491 m_vecs[ auxid ]->reserve( capacity );
492 if (m_vecs[ auxid ]->size() < size) {
493 m_vecs[ auxid ]->resize( size );
494 }
495
496 return m_vecs[ auxid ]->toPtr();
497 }
498
501
502 // Return the full list of known IDs. The constness of this object's
503 // members comes from the object being const or not.
504 return m_auxids;
505 }
506
508
509 // Guard against multi-threaded execution:
510 guard_t guard( m_mutex );
511
512 // This operation is not allowed on a locked container:
513 if( m_locked ) {
514 throw SG::ExcStoreLocked( "resize" );
515 }
516
517 // Do the operation on the static variables:
518 bool nomoves = true;
519 for (SG::IAuxTypeVector* v : m_vecs) {
520 if(v && !v->isLinked()) {
521 if (!v->resize( size ))
522 nomoves = false;
523 }
524 }
525
526 // Do the operation on the dynamic variables:
527 if( m_store ) {
528 if (!m_store->resize( size ))
529 nomoves = false;
530 }
531
532 return nomoves;
533 }
534
536
537 // Guard against multi-threaded execution:
538 guard_t guard( m_mutex );
539
540 // This operation is not allowed on a locked container:
541 if( m_locked ) {
542 throw SG::ExcStoreLocked( "reserve" );
543 }
544
545 // Do the operation on the static variables:
546 for (SG::IAuxTypeVector* v : m_vecs) {
547 if(v && !v->isLinked()) {
548 v->reserve( size );
549 }
550 }
551
552 // Do the operation on the dynamic variables:
553 if( m_store ) {
554 m_store->reserve( size );
555 }
556
557 return;
558 }
559
560 void AuxContainerBase::shift( size_t pos, ptrdiff_t offs ) {
561
562 // Guard against multi-threaded execution:
563 guard_t guard( m_mutex );
564
565 // This operation is not allowed on a locked container:
566 if( m_locked ) {
567 throw SG::ExcStoreLocked( "shift" );
568 }
569
570 // Do the operation on the static variables:
571 for (SG::IAuxTypeVector* v : m_vecs) {
572 if(v && !v->isLinked()) {
573 v->shift( pos, offs );
574 }
575 }
576
577 // Do the operation on the dynamic variables:
578 if( m_store ) {
579 m_store->shift( pos, offs );
580 }
581
582 return;
583 }
584
585
587 IAuxStore& other,
588 const SG::auxid_set_t& ignore_in ) {
589 // Guard against multi-threaded execution:
590 guard_t guard( m_mutex );
591
592 // This operation is not allowed on a locked container:
593 if( m_locked ) {
594 throw SG::ExcStoreLocked( "insertMove" );
595 }
596
597 bool nomove = true;
598 size_t other_size = other.size();
599
600 SG::auxid_set_t ignore = ignore_in;
601
602 // Do the operation on the static variables:
603 for (SG::auxid_t id : m_auxids) {
604 SG::IAuxTypeVector* v_dst = nullptr;
605 if (id < m_vecs.size())
606 v_dst = m_vecs[id];
607 // Skip linked vars --- they should be taken care of by the parent var.
608 if (v_dst && !v_dst->isLinked()) {
609 ignore.insert (id);
610 if (other.getData (id)) {
611 void* src_ptr = other.getData (id, other_size, other_size);
612 if (src_ptr) {
613 if (!v_dst->insertMove (pos, src_ptr, 0, other_size,
614 other))
615 nomove = false;
616 }
617 }
618 else {
619 const void* orig = v_dst->toPtr();
620 v_dst->shift (pos, other_size);
621 if (orig != v_dst->toPtr())
622 nomove = false;
623 }
624 }
625 }
626
627 // Do the operation on the dynamic variables:
628 if( m_store ) {
629 if (!m_store->insertMove( pos, other, ignore ))
630 nomove = false;
631
632 // Notice any new variables added as a result of this.
633 m_auxids.insert (m_store->getAuxIDs());
634 }
635
636 return nomove;
637 }
638
639
641 const SG::AuxDataOption& option ) {
642
643 guard_t guard (m_mutex);
644 if (id < m_vecs.size() && m_vecs[id] != nullptr)
645 return m_vecs[id]->setOption (option);
646
647 if (m_store)
648 return m_store->setOption (id, option);
649 return false;
650 }
651
652
653 //
655
657 //
658 // Implementation of the SG::IAuxStoreIO functions
659 //
660
661 const void* AuxContainerBase::getIOData( auxid_t auxid ) const {
662
663 // Guard against multi-threaded execution:
664 guard_t guard( m_mutex );
665
666 // If the variable is not static, look for it in the dynamic store:
667 if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ) {
668 if( m_storeIO ) {
669 return m_storeIO->getIOData( auxid );
670 } else {
671 std::cout << "ERROR xAOD::AuxContainerBase::getIOData "
672 << "Unknown variable ("
674 << ") requested" << std::endl;
675 return nullptr;
676 }
677 }
678
679 // Update the statistics for this variable. The dynamic store registers
680 // its own variable accesses.
682
683 return m_vecs[ auxid ]->toVector();
684 }
685
686 const std::type_info* AuxContainerBase::getIOType( auxid_t auxid ) const {
687
688 // Guard against multi-threaded execution:
689 guard_t guard( m_mutex );
690
691 // If the variable is not static, ask the dynamic store:
692 if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ) {
693 if( m_storeIO ) {
694 return m_storeIO->getIOType( auxid );
695 }
696 }
697
698 // Fall back on getting the information from the registry:
700 }
701
704
705 // Guard against multi-threaded execution:
706 guard_t guard( m_mutex );
707
708 // All the variables handled by the internal store are dynamic
709 // if such a store exists:
710 if( m_storeIO ) {
711 // I mean, all the variables. Not just the ones reported as dynamic
712 // by the internal object. Because the internal object may be something
713 // that was put into this one in order to achieve data slimming.
714 return m_store->getAuxIDs();
715 }
716 // In case we don't use an internal store, there are no dynamic
717 // variables:
718 static const auxid_set_t dummy (0);
719 return dummy;
720 }
721
724
725 // Guard against multi-threaded execution:
726 guard_t guard( m_mutex );
727
728 // All the variables handled by the internal store are dynamic
729 // if such a store exists:
730 if( m_storeIO ) {
731 // I mean, all the variables. Not just the ones reported as dynamic
732 // by the internal object. Because the internal object may be something
733 // that was put into this one in order to achieve data slimming.
734 return m_store->getAuxIDs();
735 }
736
737 // In case we don't use an internal store, there are no dynamic
738 // variables:
739 return auxid_set_t();
740 }
741
742 //
744
745 const char* AuxContainerBase::name() const {
746
747 return m_name.c_str();
748 }
749
750 void AuxContainerBase::setName( const char* name ) {
751
752 m_name = name;
753 return;
754 }
755
756} // namespace xAOD
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
Exceptions that can be thrown from AthContainers.
static Double_t sz
static const Attributes_t empty
Helper for getting a const version of a pointer.
Define macros for attributes used to control the static checker.
Hold information about an option setting request.
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
const std::type_info * getVecType(SG::auxid_t auxid) const
Return the type of the STL vector used to hold an aux data item.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Exception — Attempted to modify auxiliary data in a locked store.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:48
Abstract interface for manipulating vectors of arbitrary types.
bool isLinked() const
Return true if this variable is linked from another one.
virtual void * toPtr()=0
Return a pointer to the start of the vector's data.
virtual bool insertMove(size_t pos, void *src, size_t src_pos, size_t src_n, IAuxStore &srcStore)=0
Insert elements into the vector via move semantics.
virtual bool shift(size_t pos, ptrdiff_t offs)=0
Shift the elements of the vector.
A set of aux data identifiers.
Definition AuxTypes.h:47
Common base class for the auxiliary containers.
SG::auxid_set_t auxid_set_t
The aux ID set type definition.
virtual bool resize(size_t size) override
Resize the arrays to a given size.
void setName(const char *name)
Set the name of the container instance.
virtual const void * getIOData(auxid_t auxid) const override
Get a pointer to the data being stored for one aux data item.
CxxUtils::CachedPointer< std::pmr::memory_resource > m_memResource ATLAS_THREAD_SAFE
Memory resource to use for this container.
bool m_locked
Has the container been locked?
virtual bool isDecoration(auxid_t auxid) const override
Test if a variable is a decoration.
virtual SG::IAuxStore * getStore() override
Get the currently used internal store object.
virtual void lockDecoration(SG::auxid_t auxid) override
Lock a decoration.
virtual const void * getData(auxid_t auxid) const override
Get a pointer to a given array.
virtual const auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
SG::IAuxStore * m_store
Internal dynamic auxiliary store object.
virtual bool insertMove(size_t pos, IAuxStore &other, const SG::auxid_set_t &ignore) override
Insert contents of another store via move.
virtual size_t size() const override
Get the size of the container.
virtual const SG::IAuxTypeVector * getVector(SG::auxid_t auxid) const override final
Return vector interface for one aux data item.
AuxContainerBase(bool allowDynamicVars=true)
Default constructor.
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the contents of the stored arrays.
bool m_ownsStore
Flag deciding if the object owns the dynamic store or not.
virtual SG::auxid_set_t getSelectedAuxIDs() const override
Get the IDs of the selected dynamic Aux variables (for writing)
virtual const auxid_set_t & getDynamicAuxIDs() const override
Get the types(names) of variables created dynamically.
AthContainers_detail::lock_guard< mutex_t > guard_t
std::string m_name
Name of the container in memory. Set externally.
virtual void * getDecoration(auxid_t auxid, size_t size, size_t capacity) override
Get a pointer to a given array, as a decoration.
virtual void lock() override
Lock the container.
std::pmr::memory_resource * memResource()
Return the memory resource to use.
virtual const auxid_set_t & getDecorIDs() const override
Get the types(names) of decorations handled by this container.
SG::IAuxStoreIO * m_storeIO
The IO interface to the internal auxiliary store.
virtual void reserve(size_t size) override
Reserve a given size for the arrays.
auxid_set_t m_auxids
Internal list of all available variables.
virtual const std::type_info * getIOType(auxid_t auxid) const override
Return the type of the data to be stored for one aux data item.
virtual const SG::IAuxTypeVector * linkedVector(SG::auxid_t auxid) const override
Return interface for a linked variable.
virtual const auxid_set_t & getWritableAuxIDs() const override
Return a set of writable data identifiers.
std::vector< SG::IAuxTypeVector * > m_vecs
Internal list of all managed variables.
const char * name() const
Get the name of the container instance.
virtual bool clearDecorations() override
Clear all decorations.
SG::auxid_t auxid_t
The aux ID type definition.
virtual bool setOption(auxid_t id, const SG::AuxDataOption &option) override
Make an option setting on an aux variable.
AuxContainerBase & operator=(const AuxContainerBase &rhs)
Assignment operator.
ReadStats & stats()
Access the object belonging to the current thread.
Definition IOStats.cxx:17
static IOStats & instance()
Singleton object accessor.
Definition IOStats.cxx:11
void readBranch(const std::string &prefix, SG::auxid_t auxid)
Function incrementing the read counter on a specific branch.
int r
Definition globals.cxx:22
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
bool hasExtendedEventContext(const EventContext &ctx)
Test whether a context object has an extended context installed.
const T * as_const_ptr(const T *p)
Helper for getting a const version of a pointer.
Forward declaration.
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.