ATLAS Offline Software
Loading...
Searching...
No Matches
AuxStoreInternal.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
10
11
12#include <iostream>
13#include <atomic>
14#include <algorithm>
15
21
22
23namespace SG {
24
25
30AuxStoreInternal::AuxStoreInternal (bool standalone /*= false*/)
32 m_locked (false)
33{
34}
35
36
42AuxStoreInternal::~AuxStoreInternal()
43{
44}
45
46
50AuxStoreInternal::AuxStoreInternal (const AuxStoreInternal& other)
51{
52 guard_t guard (other.m_mutex);
53 m_standalone = other.m_standalone;
54 m_decorations = other.m_decorations;
55 m_auxids = other.m_auxids;
56 m_locked = other.m_locked;
57 size_t size = other.m_vecs.size();
58 m_vecs.resize (size);
59 for (size_t i = 0; i < size; i++) {
60 if (other.m_vecs[i])
61 m_vecs[i] = other.m_vecs[i]->clone();
62 }
63}
64
65
69bool AuxStoreInternal::standalone() const
70{
71 return m_standalone;
72}
73
74
85const void* AuxStoreInternal::getData (auxid_t auxid) const
86{
87 const IAuxTypeVector* v = getVector (auxid);
88 if (v) {
89 return v->toPtr();
90 }
91 return nullptr;
92}
93
94
101const IAuxTypeVector* AuxStoreInternal::getVector (auxid_t auxid) const
102{
103 guard_t guard (m_mutex);
104 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
105 // With the new behavior of SG::Accessor::isAvailable,
106 // we shouldn't print an error message here. Asking the store whether
107 // it has an element using this function is not necessarily an
108 // error condition by now. In any case, the DataVector code will
109 // complain itself in case of an error.
110 return 0;
111 }
112 return m_vecs[auxid].get();
113}
114
115
132void* AuxStoreInternal::getData (auxid_t auxid, size_t size, size_t capacity)
133{
134 return getDataInternal (auxid, size, capacity, false);
135}
136
137
145IAuxTypeVector*
146AuxStoreInternal::addVector (std::unique_ptr<IAuxTypeVector> vec,
147 bool isDecoration)
148{
149 guard_t guard (m_mutex);
150 auxid_t auxid = vec->auxid();
151 if (m_locked)
152 throw ExcStoreLocked (auxid);
153
154 // Resize the vector if needed.
155 if (m_vecs.size() <= auxid) {
156 m_vecs.resize (auxid+1);
157 }
158
159 // Give up if the variable is already present in the store.
160 if (m_vecs[auxid]) std::abort();
161
162 // Make sure the length is consistent with the rest of the store.
163 if (!vec->isLinked()) {
164 size_t sz = this->size_noLock();
165 if (vec->size() < sz)
166 vec->resize (sz);
167 }
168
169 // Add it to the store.
170 m_vecs[auxid] = std::move (vec);
171
172 // Need to be sure that the addition to the decoration bitset is visible
173 // to other threads before the addition to the variable bitset.
174 if (isDecoration) {
175 m_decorations.insert (auxid);
176 std::atomic_thread_fence (std::memory_order_seq_cst);
177 }
178 addAuxID (auxid);
179
180 return m_vecs[auxid].get();
181}
182
183
205void*
206AuxStoreInternal::getDecoration (auxid_t auxid, size_t size, size_t capacity)
207{
208 guard_t guard (m_mutex);
209 if (m_vecs.size() <= auxid) {
210 m_vecs.resize (auxid+1);
211 }
212 if (m_vecs[auxid] == 0) {
213 m_vecs[auxid] = AuxTypeRegistry::instance().makeVector (auxid, size, capacity);
214 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
215 auxid_t linked_id = null_auxid;
216 if (linked) {
217 linked_id = linked->auxid();
218 m_vecs[linked_id] = std::move (linked);
219 }
220 if (m_locked) {
221 // Need to be sure that the addition to the decoration bitset is visible
222 // to other threads before the addition to the variable bitset.
223 m_decorations.insert (auxid);
224 if (linked_id != null_auxid) {
225 m_decorations.insert (linked_id);
226 }
227 std::atomic_thread_fence (std::memory_order_seq_cst);
228 }
229 addAuxID (auxid);
230 if (linked_id != null_auxid) {
231 addAuxID (linked_id);
232 }
233 }
234 if (m_locked && !m_decorations.test (auxid)) {
235 throw ExcStoreLocked (auxid);
236 }
237 return m_vecs[auxid]->toPtr();
238}
239
240
256bool AuxStoreInternal::resize (size_t sz)
257{
258 guard_t guard (m_mutex);
259 if (m_locked)
260 throw ExcStoreLocked ("resize");
261 bool nomoves = true;
262 for (SG::auxid_t id : m_auxids) {
263 SG::IAuxTypeVector* v = nullptr;
264 if (id < m_vecs.size())
265 v = m_vecs[id].get();
266 if (v && !v->isLinked()) {
267 if (!v->resize (sz))
268 nomoves = false;
269 }
270 }
271 return nomoves;
272}
273
274
283void AuxStoreInternal::reserve (size_t sz)
284{
285 guard_t guard (m_mutex);
286 if (m_locked)
287 throw ExcStoreLocked ("reserve");
288 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
289 if (v && !v->isLinked())
290 v->reserve (sz);
291 }
292}
293
294
317void AuxStoreInternal::shift (size_t pos, ptrdiff_t offs)
318{
319 guard_t guard (m_mutex);
320 if (m_locked)
321 throw ExcStoreLocked ("shift");
322 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
323 if (v && !v->isLinked())
324 v->shift (pos, offs);
325 }
326}
327
328
348bool AuxStoreInternal::insertMove (size_t pos,
349 IAuxStore& other,
350 const SG::auxid_set_t& ignore)
351{
352 guard_t guard (m_mutex);
353 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
354
355 if (m_locked)
356 throw ExcStoreLocked ("insertMove");
357 bool nomove = true;
358 size_t other_size = other.size();
359 if (other_size == 0)
360 return true;
361 for (SG::auxid_t id : m_auxids) {
362 SG::IAuxTypeVector* v_dst = nullptr;
363 if (id < m_vecs.size())
364 v_dst = m_vecs[id].get();
365 // Skip linked vars --- they should be taken care of by the parent var.
366 if (v_dst && !v_dst->isLinked()) {
367 if (other.getData (id)) {
368 void* src_ptr = other.getData (id, other_size, other_size);
369 if (src_ptr) {
370 if (!v_dst->insertMove (pos, src_ptr, 0, other_size,
371 other))
372 nomove = false;
373 }
374 }
375 else {
376 const void* orig = v_dst->toPtr();
377 v_dst->shift (pos, other_size);
378 if (orig != v_dst->toPtr())
379 nomove = false;
380 }
381 }
382 }
383
384 // Add any new variables not present in the original container.
385 for (SG::auxid_t id : other.getAuxIDs()) {
386 if (!m_auxids.test(id) && !ignore.test(id))
387 {
388 if (r.isLinked (id)) continue;
389 if (other.getData (id)) {
390 void* src_ptr = other.getData (id, other_size, other_size);
391 if (src_ptr) {
392 size_t sz = size_noLock();
393 if (sz < other_size) sz = other_size + pos;
394 IAuxTypeVector* v = getVectorInternal_noLock (id, sz, sz, false);
395 v->resize (sz - other_size);
396 (void)v->insertMove (pos, src_ptr, 0, other_size,
397 other);
398 nomove = false;
399 }
400 }
401 }
402 }
403
404 return nomove;
405}
406
407
415const SG::auxid_set_t&
416AuxStoreInternal::getAuxIDs() const
417{
418 return m_auxids;
419}
420
421
425const SG::auxid_set_t&
426AuxStoreInternal::getDecorIDs() const
427{
428 return m_decorations;
429}
430
431
437SG::auxid_set_t AuxStoreInternal::getCopyIDs (bool warnUnlocked) const
438{
439 return SG::getCopyIDs (m_auxids, m_decorations, warnUnlocked, {});
440}
441
442
447bool AuxStoreInternal::isDecoration (auxid_t auxid) const
448{
449 return m_decorations.test (auxid);
450}
451
452
459const SG::auxid_set_t&
460AuxStoreInternal::getWritableAuxIDs() const
461{
462 return getAuxIDs();
463}
464
465
477const void* AuxStoreInternal::getIODataInternal (auxid_t auxid, bool quiet) const
478{
479 guard_t guard (m_mutex);
480 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
481 if (!quiet) {
482 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal",
483 "Requested variable {} ({}) doesn't exist",
485 }
486 return 0;
487 }
488
489 if (m_standalone) {
490 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
491 return m_vecs[auxid]->toPtr();
492 }
493 return m_vecs[auxid]->toVector();
494}
495
496
508void* AuxStoreInternal::getIODataInternal (auxid_t auxid, bool quiet)
509{
510 guard_t guard (m_mutex);
511 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
512 if (!quiet) {
513 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal",
514 "Requested variable {} ({}) doesn't exist",
515 SG::AuxTypeRegistry::instance().getName (auxid), auxid);
516 }
517 return 0;
518 }
519
520 if (m_standalone) {
521 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
522 return m_vecs[auxid]->toPtr();
523 }
524 return m_vecs[auxid]->toVector();
525}
526
527
538const void* AuxStoreInternal::getIOData (auxid_t auxid) const
539{
540 return getIODataInternal (auxid, false);
541}
542
543
555const std::type_info* AuxStoreInternal::getIOType (auxid_t auxid) const
556{
557 if (m_standalone) {
559 if (!r.isLinked (auxid))
560 return r.getType (auxid);
561 }
562 guard_t guard (m_mutex);
563 if (auxid < m_vecs.size() && m_vecs[auxid]) {
564 const std::type_info* ret = m_vecs[auxid]->objType();
565 if (ret) return ret;
566 }
568}
569
570
574const SG::auxid_set_t&
575AuxStoreInternal::getDynamicAuxIDs() const
576{
577 return getAuxIDs();
578}
579
580
587void AuxStoreInternal::lock()
588{
589 guard_t guard (m_mutex);
590 m_locked = true;
591}
592
593
604bool AuxStoreInternal::clearDecorations()
605{
606 guard_t guard (m_mutex);
607 bool anycleared = false;
608 for (auxid_t id : m_decorations) {
609 m_vecs[id].reset();
610 m_auxids.erase (id);
611 anycleared = true;
612 }
613 if (anycleared) {
614 m_decorations.clear();
615 }
616 return anycleared;
617}
618
619
625size_t AuxStoreInternal::size() const
626{
627 guard_t guard (m_mutex);
628 return size_noLock();
629}
630
631
637size_t AuxStoreInternal::size_noLock() const
638{
639 for (SG::auxid_t id : m_auxids) {
640 if (id < m_vecs.size() && m_vecs[id] && !m_vecs[id]->isLinked() &&
641 m_vecs[id]->size() > 0)
642 {
643 return m_vecs[id]->size();
644 }
645 }
646 return 0;
647}
648
649
659bool AuxStoreInternal::setOption (auxid_t id, const AuxDataOption& option)
660{
661 // Does this variable exist in this store?
662 bool exists = false;
663 {
664 guard_t guard (m_mutex);
665 if (id < m_vecs.size() && m_vecs[id] != 0)
666 exists = true;
667 }
668
669 // If not, and we have a packing parameter request, then create the variable.
670 if (!exists) {
671 if (!PackedParameters::isValidOption (option)) return false;
672 size_t sz = size();
673 getDataInternal (id, sz, sz, true);
674 }
675
676 // Try the option setting.
677 guard_t guard (m_mutex);
678 if (m_vecs[id]->setOption (option)) return true;
679
680 // It didn't work. If this is a packing request, then try to convert
681 // the variable to packed form and retry.
682 if (!PackedParameters::isValidOption (option)) return false;
683 std::unique_ptr<IAuxTypeVector> packed = m_vecs[id]->toPacked();
684 if (packed) {
685 // Converted to packed form. Replace the object and retry.
686 m_vecs[id] = std::move (packed);
687 return m_vecs[id]->setOption (option);
688 }
689
690 // Didn't work.
691 return false;
692}
693
694
699void AuxStoreInternal::addAuxID (auxid_t auxid)
700{
701 m_auxids.insert (auxid);
702}
703
704
706IAuxTypeVector*
707AuxStoreInternal::getVectorInternal_noLock (auxid_t auxid,
708 size_t size,
709 size_t capacity,
710 bool no_lock_check)
711{
712 if (m_vecs.size() <= auxid) {
713 m_vecs.resize (auxid+1);
714 }
715 if (m_vecs[auxid] == 0) {
716 if (m_locked && !no_lock_check)
717 throw ExcStoreLocked (auxid);
719 m_vecs[auxid] = r.makeVector (auxid, size, capacity);
720 addAuxID (auxid);
721 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
722 if (linked) {
723 auxid_t linked_id = linked->auxid();
724 m_vecs[linked_id] = std::move (linked);
725 addAuxID (linked_id);
726 }
727 }
728 else {
729 // Make sure the vector has at least the requested size.
730 // One way in which it could be short: setOption was called and created
731 // a variable in a store that had no other variables.
732 if (m_vecs[auxid]->size() < size) {
733 m_vecs[auxid]->resize (size);
734 m_vecs[auxid]->reserve (capacity);
735 }
736 }
737 return m_vecs[auxid].get();
738}
739
740
758void* AuxStoreInternal::getDataInternal (auxid_t auxid,
759 size_t size,
760 size_t capacity,
761 bool no_lock_check)
762{
763 guard_t guard (m_mutex);
764 return getVectorInternal_noLock (auxid, size, capacity, no_lock_check)->toPtr();
765}
766
767
776void AuxStoreInternal::lockDecoration (SG::auxid_t auxid)
777{
778 guard_t guard (m_mutex);
779 m_decorations.reset (auxid);
780}
781
782
792IAuxTypeVector* AuxStoreInternal::linkedVector (SG::auxid_t auxid)
793{
794 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
795 auxid_t linked_id = r.linkedVariable (auxid);
796 guard_t guard (m_mutex);
797 if (linked_id < m_vecs.size())
798 return m_vecs[linked_id].get();
799 return nullptr;
800}
801
802
812const IAuxTypeVector* AuxStoreInternal::linkedVector (SG::auxid_t auxid) const
813{
814 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
815 auxid_t linked_id = r.linkedVariable (auxid);
816 guard_t guard (m_mutex);
817 if (linked_id < m_vecs.size())
818 return m_vecs[linked_id].get();
819 return nullptr;
820}
821
822
833void AuxStoreInternal::toTransient (const EventContext& ctx, SG::auxid_t auxid)
834{
835 guard_t guard (m_mutex);
836 if (auxid < m_vecs.size() && m_vecs[auxid]) {
837 m_vecs[auxid]->toTransient (ctx);
838 }
839}
840
841
852void AuxStoreInternal::toTransient (const EventContext& ctx)
853{
854 guard_t guard (m_mutex);
855 size_t sz = m_vecs.size();
856 for (SG::auxid_t id : m_auxids) {
857 if (id < sz && m_vecs[id]) {
858 m_vecs[id]->toTransient (ctx);
859 }
860 }
861}
862
863
875 const SG::auxid_set_t& decors,
876 [[maybe_unused]] bool warnUnlocked,
877 [[maybe_unused]] std::span<const std::string> noWarn)
878{
879 SG::auxid_set_t out = auxids;
880#ifndef XAOD_STANDALONE
881 if (warnUnlocked) {
883 for (SG::auxid_t decor : decors) {
884 if (out.test (decor)) {
885 out.reset (decor);
886 if (std::ranges::find (noWarn, r.getName (decor)) == noWarn.end()) {
887 ATHCONTAINERS_WARNING("getCopyAuxIDs",
888 "skipped unlocked decoration during copy {} ({})",
889 r.getName(decor), decor);
890 }
891 }
892 }
893 }
894 else
895#endif
896 out -= decors;
897 return out;
898}
899
900
901} // namespace SG
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
std::vector< size_t > vec
Exceptions that can be thrown from AthContainers.
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
static Double_t sz
Describe how the contents of a PackedContainer are to be saved.
size_t size() const
Number of registered mappings.
Handle mappings between names and auxid_t.
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.
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
bool exists(const std::string &filename)
does a file exist
Helper for emitting error messages.
#define ATHCONTAINERS_ERROR(ctx, msg,...)
Definition error.h:62
#define ATHCONTAINERS_WARNING(ctx, msg,...)
Definition error.h:65
int r
Definition globals.cxx:22
H5::CompType packed(H5::CompType in)
Forward declaration.
virtual void * getDataInternal(SG::auxid_t auxid, size_t size, size_t capacity, bool no_lock_check)
Return the data vector for one aux data item.
bool standalone() const
Return the standalone flag.
void addAuxID(auxid_t auxid)
Add a new auxid to the set of those being managed by this store.
virtual SG::auxid_set_t getCopyIDs(bool warnUnlocked=false) const override
Return the set of variables to copy in a deep copy.
virtual IAuxTypeVector * getVectorInternal_noLock(SG::auxid_t auxid, size_t size, size_t capacity, bool no_lock_check)
Implementation of getVectorInternal; no locking.
SG::auxid_set_t m_decorations
Record which variables are decorations.
SG::auxid_t auxid() const
Return the aux id for this variable.
const void * getIODataInternal(auxid_t auxid, bool quiet) const
Return a pointer to the data to be stored for one aux data item.
virtual bool isDecoration(auxid_t auxid) const override
Test if a particular variable is tagged as a decoration.
AthContainers_detail::lock_guard< mutex_t > guard_t
std::vector< std::unique_ptr< IAuxTypeVector > > m_vecs
The collection of vectors of aux data that we're managing, indexed by auxid.
SG::auxid_set_t m_auxids
Set of auxid's for which we've created a vector.
virtual size_t size() const override
Return the number of elements in the store.
bool m_locked
Has this container been locked?
mutex_t m_mutex
const SG::auxid_set_t & getAuxIDs() const
Return a set of identifiers for existing data items for this object.
size_t size_noLock() const
Return the number of elements in the store; no locking.
bool m_standalone
Are we being written in standalone mode?
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27