ATLAS Offline Software
Loading...
Searching...
No Matches
ShallowAuxContainer.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// System include(s):
6#include <iostream>
7#include <sstream>
8#include <stdexcept>
9#include <atomic>
10
11// EDM include(s):
17
18// Local include(s):
20
21namespace {
22
23
24} // anonymous namespace
25
26
27namespace xAOD {
28
33 : m_selection(),
34 m_store( new SG::AuxStoreInternal( standalone ) ),
35 m_storeIO( nullptr ), m_ownsStore( true ), m_locked( false ),
36 m_parentLink(), m_parentIO( nullptr ), m_shallowIO( true ),
37 m_auxids (),
38 m_auxidsValid (false),
39 m_name( "UNKNOWN" ) {
40
41 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
42 }
43
45 : SG::IAuxStore(), SG::IAuxStoreIO(), SG::IAuxStoreHolder(),
46 m_ownsStore( false ),
47 m_auxids (),
48 m_auxidsValid (false)
49 {
50 // Keep the source unmutable during copy
51 guard_t guard( parent.m_mutex );
52 // cppcheck-suppress copyCtorPointerCopying
53 m_store = parent.m_store;
54 m_storeIO = parent.m_storeIO;
55 m_locked = parent.m_locked;
56 m_parentLink = parent.m_parentLink;
57 m_parentIO = parent.m_parentIO;
58 m_shallowIO = parent.m_shallowIO;
59 m_selection = parent.m_selection;
60 m_name = parent.m_name;
61 }
62
69 bool standalone )
70 : m_selection(),
71 m_store( new SG::AuxStoreInternal( standalone ) ),
72 m_storeIO( nullptr ), m_ownsStore( true ), m_locked( false ),
73 m_parentLink( parent ), m_parentIO( nullptr ), m_shallowIO( true ),
74 m_auxids (),
75 m_auxidsValid (false),
76 m_name( "UNKNOWN" ) {
77
78 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
79 m_parentIO = dynamic_cast< const SG::IAuxStoreIO* >( m_parentLink.cptr() );
80 }
81
83
84 if( m_ownsStore && m_store ) {
85 delete m_store;
86 }
87 }
88
91
92 // Check if anything needs to be done:
93 if( this == &rhs ) {
94 return *this;
95 }
96
97 // Keep the source unmutable during copy
98 std::scoped_lock lck{m_mutex, rhs.m_mutex};
99
100 // Clean up if necessary:
101 if( m_ownsStore && m_store ) {
102 delete m_store;
103 m_store = nullptr;
104 }
105
107 m_ownsStore = false;
108 m_store = rhs.m_store;
109 m_storeIO = rhs.m_storeIO;
110 m_locked = rhs.m_locked;
114 m_name = rhs.m_name;
115 m_auxids = rhs.m_auxids;
116 m_auxidsValid= rhs.m_auxidsValid;
117
118 // Return this object:
119 return *this;
120 }
121
126
129
130 guard_t guard (m_mutex);
131 m_parentLink = link;
132 m_parentIO = dynamic_cast< const SG::IAuxStoreIO* >( m_parentLink.cptr() );
133 m_auxidsValid = false;
134 return;
135 }
136
138
139 return m_shallowIO;
140 }
141
143
144 guard_t guard (m_mutex);
145 m_shallowIO = value;
146 return;
147 }
148
150 //
151 // Implementation of the SG::IAuxStoreHolder interface
152 //
153
158
160 {
161 return m_store;
162 }
163
165
166 // Check if anything needs to be done:
167 guard_t guard (m_mutex);
168 if( store == m_store ) return;
169
170 if( m_ownsStore && m_store ) {
171 delete m_store;
172 m_store = nullptr;
173 }
174
175 // Do the assignment:
176 m_store = store;
177 m_storeIO = dynamic_cast< SG::IAuxStoreIO* >( m_store );
178 m_ownsStore = true;
179 m_auxidsValid = false;
180
181 return;
182 }
183
184 //
186
188 //
189 // Implementation of the SG::IConstAuxStore interface
190 //
191
192 const void* ShallowAuxContainer::getData( auxid_t auxid ) const {
193
194 const SG::IAuxTypeVector* v = getVector( auxid );
195 if( v ) {
196 return v->toPtr();
197 }
198 return nullptr;
199 }
200
202
203 guard_t guard( m_mutex );
204
205 // Check if we have this variable ourselves. I use getData(...)
206 // instead of getAuxIDs(), as a dynamic store may not have connected
207 // to all the variables yet that it has available...
208 size_t nids = m_store->getAuxIDs().size();
209 const SG::IAuxTypeVector* result = m_store->getVector( auxid );
210 if( result != nullptr && result->toPtr() != nullptr ) {
211 if( nids != m_store->getAuxIDs().size() ) {
212 remakeAuxIDs();
213 }
214 return result;
215 }
216
217 // If not, then leave it up to the parent object do deal with this:
218 if( m_parentLink.isValid() ) {
219 nids = m_parentLink->getAuxIDs().size();
220 result = m_parentLink->getVector( auxid );
221 if( result && ( nids != m_parentLink->getAuxIDs().size() ) ) {
222 remakeAuxIDs();
223 }
224 return result;
225 }
226
227 // Apparently the variable wasn't found:
228 return nullptr;
229 }
230
233
234 guard_t guard( m_mutex );
235 if (!m_auxidsValid) {
236 remakeAuxIDs();
237 }
238 return m_auxids;
239 }
240
243
244 guard_t guard( m_mutex );
245 if (!m_auxidsValid) {
246 remakeAuxIDs();
247 }
248 return m_decorids;
249 }
250
252 {
253 guard_t guard( m_mutex );
254 auxid_set_t ids;
255 if( m_parentLink.isValid() ) {
256 ids.insert (m_parentLink->getCopyIDs (warnUnlocked));
257 }
258 ids.insert (m_store->getCopyIDs (warnUnlocked));
259 return ids;
260 }
261
263 {
264 guard_t guard( m_mutex );
265 if (m_parentLink.isValid()) {
266 if (m_parentLink->isDecoration (auxid)) {
267 return true;
268 }
269 }
270 return m_store->isDecoration (auxid);
271 }
272
275 size_t size,
276 size_t capacity ) {
277
278 guard_t guard( m_mutex );
279
280 // Check if we already have this variable by any chance.
281 const void* cptr = m_store->getData( auxid );
282
283 // If the parent has such a variable, then we need to check one more
284 // thing. If it's a decoration on the parent, then we should be allowed
285 // to override it in this (possibly locked) shallow copy. But let's leave
286 // the logic of this up to the parent.
287 if( m_locked && m_parentLink.isValid() &&
288 ( m_parentLink->getAuxIDs().count( auxid ) > 0 ) )
289 {
290 if (!m_parentLink->isDecoration (auxid)) {
291 throw SG::ExcStoreLocked (auxid);
292 }
293 }
294
295 // If we got this far without any exception, then let the internal store
296 // try to provide the decoration for us:
297 const size_t nids = m_store->getAuxIDs().size();
298 void* result = m_store->getDecoration( auxid, size, capacity );
299 if( result && ( nids != m_store->getAuxIDs().size() ) ) {
300 remakeAuxIDs();
301 }
302
303 // If we already had this variable before, then don't try to overwrite it
304 // with the parent's payload, and finish here already.
305 if( cptr != nullptr ) {
306 return result;
307 }
308
309 // If the parent doesn't have this variable, then we're done.
310 if( ! m_parentLink.isValid() ) {
311 return result;
312 }
313 const void* pptr = m_parentLink->getData( auxid );
314 if( pptr == nullptr ) {
315 return result;
316 }
317
318 // If the variable does exist in the parent, then copy it over to this
319 // store before returning.
320
321 // Get the registry.
323
324 // Get the type of this variable.
325 const std::type_info* type = reg.getType( auxid );
326 if( type == nullptr ) {
327 std::ostringstream message;
328 message << "Couldn't find the type of auxiliary ID " << auxid;
329 throw std::runtime_error( message.str() );
330 }
331
332 // And the allocator type for this variable.
333 const std::type_info* allocType = reg.getAllocType( auxid );
334 if( allocType == nullptr ) {
335 std::ostringstream message;
336 message << "Couldn't find the allocator type of auxiliary ID " << auxid;
337 throw std::runtime_error( message.str() );
338 }
339
340 // Get the vector factory of this variable.
341 const SG::IAuxTypeVectorFactory* factory =
343 if( factory == nullptr ) {
344 std::ostringstream message;
345 message << "Couldn't find a factory for type " << type->name();
346 throw std::runtime_error( message.str() );
347 }
348
349 // Copy each element of the parent's decoration.
350 factory->copy( auxid,
351 SG::AuxVectorInterface( *this ), 0,
353
354 // Now we're done.
355 return result;
356 }
357
358
361 {
362 guard_t guard (m_mutex);
363 m_locked = true;
364 m_store->lock();
365 }
366
367
370 {
371 guard_t guard (m_mutex);
372 m_store->lockDecoration (auxid);
373 m_auxidsValid = false;
374 }
375
377
378 guard_t guard( m_mutex );
379 size_t sz = m_store->size();
380 if( sz > 0 ) {
381 return sz;
382 }
383 if( m_parentLink.isValid() ) {
384 return m_parentLink->size();
385 }
386 return 0;
387 }
388
391 {
392 guard_t guard (m_mutex);
393 bool ret = m_store->clearDecorations();
394 if (ret) {
395 remakeAuxIDs();
396 }
397 return ret;
398 }
399
400
401 //
403
405 //
406 // Implementation of the SG::IAuxStore interface
407 //
408
410 size_t capacity ) {
411
412 guard_t guard (m_mutex);
413
414 // Check if we already have this variable by any chance.
415 const void* cptr = m_store->getData( auxid );
416
417 // Create the variable in the dynamic store:
418 void* ptr = m_store->getData( auxid, size, capacity );
419
420 remakeAuxIDs();
421
422 // If in some weird way we already had this variable before, then don't
423 // try to overwrite it with the parent's payload, and finish here already.
424 if( cptr != nullptr ) {
425 return ptr;
426 }
427
428 // If the parent doesn't have this variable, then we're done already:
429 if( ! m_parentLink.isValid() ) {
430 return ptr;
431 }
432 const void* pptr = m_parentLink->getData( auxid );
433 if( ! pptr ) {
434 return ptr;
435 }
436
437 // If the variable does exist in the parent, then copy it over to this
438 // store before returning.
439
440 // Get the registry:
442
443 // Get the type of this variable:
444 const std::type_info* type = reg.getType( auxid );
445 if( type == nullptr ) {
446 std::ostringstream message;
447 message << "Couldn't find the type of auxiliary ID " << auxid;
448 throw std::runtime_error( message.str() );
449 }
450
451 // And the allocator type for this variable.
452 const std::type_info* allocType = reg.getAllocType( auxid );
453 if( allocType == nullptr ) {
454 std::ostringstream message;
455 message << "Couldn't find the allocator type of auxiliary ID " << auxid;
456 throw std::runtime_error( message.str() );
457 }
458
459 // First let's get the vector factory of this variable:
460 const SG::IAuxTypeVectorFactory* factory =
462 if( factory == nullptr ) {
463 std::ostringstream message;
464 message << "Couldn't find a factory for type " << type->name();
465 throw std::runtime_error( message.str() );
466 }
467
468 // Copy each element of the parent's decoration:
469 factory->copy( auxid,
470 SG::AuxVectorInterface( *this ), 0,
472
473 // Now we're done:
474 return ptr;
475 }
476
479
480 // Only the variables in the dynamic store are writable. Maybe not
481 // even all of those...
482 return m_store->getWritableAuxIDs();
483 }
484
486 {
487 if (size == this->size()) {
488 return false;
489 }
490 // Nope, not allowed...
491 throw std::runtime_error( "Trying to call resize on a shallow copy "
492 "container" );
493 }
494
495 void ShallowAuxContainer::reserve( size_t /*size*/ ) {
496
497 // Nope, not allowed...
498 throw std::runtime_error( "Trying to call reserve on a shallow copy "
499 "container" );
500 }
501
502 void ShallowAuxContainer::shift( size_t /*pos*/, ptrdiff_t /*offs*/ ) {
503
504 // Nope, not allowed...
505 throw std::runtime_error( "Trying to call shift on a shallow copy "
506 "container" );
507 }
508
510 IAuxStore& /*other*/,
511 const SG::auxid_set_t& /*ignore*/) {
512
513 // Nope, not allowed...
514 throw std::runtime_error( "Trying to call insertMove on a shallow copy "
515 "container" );
516 }
517
518 //
520
522 //
523 // Implementation of the SG::IAuxStoreIO interface
524 //
525
526 const void* ShallowAuxContainer::getIOData( auxid_t auxid ) const {
527
528 guard_t guard (m_mutex);
529 // Do we have it?
530 if( m_storeIO && m_store->getAuxIDs().test (auxid)) {
531 return m_storeIO->getIOData( auxid );
532 }
533
534 // Do we have a parent that has it?
535 const SG::IAuxStoreIO* parentIO = m_parentIO;
536 if( ( parentIO == nullptr ) && m_parentLink.isValid() ) {
537 parentIO =
538 dynamic_cast< const SG::IAuxStoreIO* >( m_parentLink.cptr() );
539 }
540 if( parentIO ) {
541 return parentIO->getIOData( auxid );
542 }
543
544 // If not, then where did this variable come from?!?
545 std::cerr << "ERROR xAOD::ShallowAuxContainer::getIOData Unknown "
546 << "variable ("
548 << ") requested" << std::endl;
549 return nullptr;
550 }
551
552 const std::type_info* ShallowAuxContainer::getIOType( auxid_t auxid ) const {
553
554 guard_t guard (m_mutex);
555 // Do we have it?
556 if( m_storeIO && m_store->getAuxIDs().test (auxid)) {
557 return m_storeIO->getIOType( auxid );
558 }
559
560 // Do we have a parent that has it?
561 const SG::IAuxStoreIO* parentIO = m_parentIO;
562 if( ( parentIO == nullptr ) && m_parentLink.isValid() ) {
563 parentIO =
564 dynamic_cast< const SG::IAuxStoreIO* >( m_parentLink.cptr() );
565 }
566 if( parentIO ) {
567 return parentIO->getIOType( auxid );
568 }
569
570 // If not, then where did this variable come from?!?
571 std::cerr << "ERROR xAOD::ShallowAuxContainer::getIOType Unknown "
572 << "variable ("
574 << ") requested" << std::endl;
575 return nullptr;
576 }
577
580
581 if( m_shallowIO ) {
582 if( m_storeIO ) {
583 return m_store->getAuxIDs();
584 } else {
585 static const auxid_set_t dummy (0);
586 return dummy;
587 }
588 } else {
589 return getAuxIDs();
590 }
591 }
592
595
596 if( m_shallowIO ) {
597 if( m_storeIO ) {
598 return m_selection.getSelectedAuxIDs( m_store->getAuxIDs() );
599 } else {
600 return auxid_set_t();
601 }
602 } else {
603 return m_selection.getSelectedAuxIDs( getAuxIDs() );
604 }
605 }
606
607
608 //
610
611 const char* ShallowAuxContainer::name() const {
612
613 return m_name.c_str();
614 }
615
616 void ShallowAuxContainer::setName( const char* name ) {
617
618 m_name = name;
619 return;
620 }
621
623 auxid_set_t ids = m_store->getAuxIDs();
624 if( m_parentLink.isValid() ) {
625 ids.insert (m_parentLink->getAuxIDs());
626 }
627
628 auxid_set_t decors = m_store->getDecorIDs();
629 if( m_parentLink.isValid() ) {
630 ids.insert (m_parentLink->getDecorIDs());
631 }
632
633 m_decorids = std::move(decors);
634 std::atomic_thread_fence( std::memory_order_seq_cst );
635 m_auxids = std::move(ids);
636
637 m_auxidsValid = true;
638 }
639
640} // namespace xAOD
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
Make an AuxVectorData object from either a raw vector or an aux store.
Exceptions that can be thrown from AthContainers.
Interface for factory objects that create vectors.
static Double_t sz
Handle mappings between names and auxid_t.
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
const IAuxTypeVectorFactory * getFactory(const std::type_info &ti, const std::type_info &ti_alloc)
Return the vector factory for a given vector element type.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Make an AuxVectorData object from either a raw array or an aux store.
Exception — Attempted to modify auxiliary data in a locked store.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
virtual const std::type_info * getIOType(SG::auxid_t auxid) const =0
Return the type of the data to be stored for one aux data item.
virtual const void * getIOData(SG::auxid_t auxid) const =0
Return a pointer to the data to be stored for one aux data item.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:48
Interface for factory objects that create vectors.
virtual void copy(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const =0
Copy elements between vectors.
Abstract interface for manipulating vectors of arbitrary types.
A set of aux data identifiers.
Definition AuxTypes.h:47
Class creating a shallow copy of an existing auxiliary container.
virtual const SG::IAuxTypeVector * getVector(SG::auxid_t auxid) const override final
Return vector interface for one aux data item.
bool m_locked
Flag keeping track of whether this object is locked or not.
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the contents of the stored arrays.
virtual void setStore(SG::IAuxStore *store) override
Set a different internal store object.
SG::IAuxStore * m_store
Internal dynamic auxiliary store object.
ShallowAuxContainer(bool standalone=false)
Default constructor.
AthContainers_detail::lock_guard< mutex_t > guard_t
bool m_shallowIO
Flag for whether to do "shallow IO" or not.
virtual const auxid_set_t & getWritableAuxIDs() const override
Return a set of writable data identifiers.
virtual const void * getData(auxid_t auxid) const override
Get a pointer to a given array.
void setParent(const DataLink< SG::IConstAuxStore > &link)
Set the parent store.
virtual const auxid_set_t & getDynamicAuxIDs() const override
Get the types(names) of variables created dynamically.
bool m_ownsStore
Flag deciding if the object owns the dynamic store or not.
void setName(const char *name)
Set the name of the container instance.
bool shallowIO() const
Check whether only the overriden parameters will be written out or not.
virtual SG::IAuxStore * getStore() override
Get the currently used internal store object.
SG::IAuxStoreIO * m_storeIO
The IO interface to the internal auxiliary store.
const char * name() const
Get the name of the container instance.
SG::auxid_set_t auxid_set_t
The aux ID set type definition.
virtual const void * getIOData(auxid_t auxid) const override
Get a pointer to the data being stored for one aux data item.
virtual void lock() override
Lock the container.
virtual SG::auxid_set_t getCopyIDs(bool warnUnlocked=false) const override
Get the set of variables that we should deep copy.
virtual bool isDecoration(auxid_t auxid) const override
Test if a variable is a decoration.
virtual const auxid_set_t & getDecorIDs() const override
Get the types(names) of decorations handled by this container.
ShallowAuxContainer & operator=(const ShallowAuxContainer &rhs)
Assignment operator.
virtual void lockDecoration(SG::auxid_t auxid) override
Lock a decoration.
DataLink< SG::IConstAuxStore > m_parentLink
Link to the parent object.
SG::auxid_t auxid_t
The aux ID type definition.
virtual void reserve(size_t size) override
Reserve a given size for the arrays.
virtual size_t size() const override
Get the size of the container.
const SG::IAuxStoreIO * m_parentIO
Optional pointer to the IO interface of the parent object.
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.
void setShallowIO(bool value)
Set whether only the overriden parameters should be written out.
AuxSelection m_selection
Dynamic attributes selection implementation.
virtual bool clearDecorations() override
Clear all decorations.
virtual auxid_set_t getSelectedAuxIDs() const override
Get the IDs of the selected dynamic Aux variables (for writing).
std::string m_name
Name of the container in memory. Set externally.
virtual bool resize(size_t size) override
Resize the arrays to a given size.
virtual bool insertMove(size_t pos, IAuxStore &other, const SG::auxid_set_t &ignore) override
Insert contents of another store via move.
virtual void * getDecoration(auxid_t auxid, size_t size, size_t capacity) override
Return the data vector for one aux data decoration item.
virtual const auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
const DataLink< SG::IConstAuxStore > & parent() const
Get the parent store.
Forward declaration.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.