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 <sstream>
14#include <atomic>
15#include <algorithm>
16
22
23
24namespace SG {
25
26
31AuxStoreInternal::AuxStoreInternal (bool standalone /*= false*/)
33 m_locked (false)
34{
35}
36
37
43AuxStoreInternal::~AuxStoreInternal()
44{
45}
46
47
51AuxStoreInternal::AuxStoreInternal (const AuxStoreInternal& other)
52{
53 guard_t guard (other.m_mutex);
54 m_standalone = other.m_standalone;
55 m_decorations = other.m_decorations;
56 m_auxids = other.m_auxids;
57 m_locked = other.m_locked;
58 size_t size = other.m_vecs.size();
59 m_vecs.resize (size);
60 for (size_t i = 0; i < size; i++) {
61 if (other.m_vecs[i])
62 m_vecs[i] = other.m_vecs[i]->clone();
63 }
64}
65
66
70bool AuxStoreInternal::standalone() const
71{
72 return m_standalone;
73}
74
75
86const void* AuxStoreInternal::getData (auxid_t auxid) const
87{
88 const IAuxTypeVector* v = getVector (auxid);
89 if (v) {
90 return v->toPtr();
91 }
92 return nullptr;
93}
94
95
102const IAuxTypeVector* AuxStoreInternal::getVector (auxid_t auxid) const
103{
104 guard_t guard (m_mutex);
105 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
106 // With the new behavior of SG::Accessor::isAvailable,
107 // we shouldn't print an error message here. Asking the store whether
108 // it has an element using this function is not necessarily an
109 // error condition by now. In any case, the DataVector code will
110 // complain itself in case of an error.
111 return 0;
112 }
113 return m_vecs[auxid].get();
114}
115
116
133void* AuxStoreInternal::getData (auxid_t auxid, size_t size, size_t capacity)
134{
135 return getDataInternal (auxid, size, capacity, false);
136}
137
138
146IAuxTypeVector*
147AuxStoreInternal::addVector (std::unique_ptr<IAuxTypeVector> vec,
148 bool isDecoration)
149{
150 guard_t guard (m_mutex);
151 auxid_t auxid = vec->auxid();
152 if (m_locked)
153 throw ExcStoreLocked (auxid);
154
155 // Resize the vector if needed.
156 if (m_vecs.size() <= auxid) {
157 m_vecs.resize (auxid+1);
158 }
159
160 // Give up if the variable is already present in the store.
161 if (m_vecs[auxid]) std::abort();
162
163 // Make sure the length is consistent with the rest of the store.
164 if (!vec->isLinked()) {
165 size_t sz = this->size_noLock();
166 if (vec->size() < sz)
167 vec->resize (sz);
168 }
169
170 // Add it to the store.
171 m_vecs[auxid] = std::move (vec);
172
173 // Need to be sure that the addition to the decoration bitset is visible
174 // to other threads before the addition to the variable bitset.
175 if (isDecoration) {
176 m_decorations.insert (auxid);
177 std::atomic_thread_fence (std::memory_order_seq_cst);
178 }
179 addAuxID (auxid);
180
181 return m_vecs[auxid].get();
182}
183
184
206void*
207AuxStoreInternal::getDecoration (auxid_t auxid, size_t size, size_t capacity)
208{
209 guard_t guard (m_mutex);
210 if (m_vecs.size() <= auxid) {
211 m_vecs.resize (auxid+1);
212 }
213 if (m_vecs[auxid] == 0) {
214 m_vecs[auxid] = AuxTypeRegistry::instance().makeVector (auxid, size, capacity);
215 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
216 auxid_t linked_id = null_auxid;
217 if (linked) {
218 linked_id = linked->auxid();
219 m_vecs[linked_id] = std::move (linked);
220 }
221 if (m_locked) {
222 // Need to be sure that the addition to the decoration bitset is visible
223 // to other threads before the addition to the variable bitset.
224 m_decorations.insert (auxid);
225 if (linked_id != null_auxid) {
226 m_decorations.insert (linked_id);
227 }
228 std::atomic_thread_fence (std::memory_order_seq_cst);
229 }
230 addAuxID (auxid);
231 if (linked_id != null_auxid) {
232 addAuxID (linked_id);
233 }
234 }
235 if (m_locked && !m_decorations.test (auxid)) {
236 throw ExcStoreLocked (auxid);
237 }
238 return m_vecs[auxid]->toPtr();
239}
240
241
257bool AuxStoreInternal::resize (size_t sz)
258{
259 guard_t guard (m_mutex);
260 if (m_locked)
261 throw ExcStoreLocked ("resize");
262 bool nomoves = true;
263 for (SG::auxid_t id : m_auxids) {
264 SG::IAuxTypeVector* v = nullptr;
265 if (id < m_vecs.size())
266 v = m_vecs[id].get();
267 if (v && !v->isLinked()) {
268 if (!v->resize (sz))
269 nomoves = false;
270 }
271 }
272 return nomoves;
273}
274
275
284void AuxStoreInternal::reserve (size_t sz)
285{
286 guard_t guard (m_mutex);
287 if (m_locked)
288 throw ExcStoreLocked ("reserve");
289 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
290 if (v && !v->isLinked())
291 v->reserve (sz);
292 }
293}
294
295
318void AuxStoreInternal::shift (size_t pos, ptrdiff_t offs)
319{
320 guard_t guard (m_mutex);
321 if (m_locked)
322 throw ExcStoreLocked ("shift");
323 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
324 if (v && !v->isLinked())
325 v->shift (pos, offs);
326 }
327}
328
329
349bool AuxStoreInternal::insertMove (size_t pos,
350 IAuxStore& other,
351 const SG::auxid_set_t& ignore)
352{
353 guard_t guard (m_mutex);
354 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
355
356 if (m_locked)
357 throw ExcStoreLocked ("insertMove");
358 bool nomove = true;
359 size_t other_size = other.size();
360 if (other_size == 0)
361 return true;
362 for (SG::auxid_t id : m_auxids) {
363 SG::IAuxTypeVector* v_dst = nullptr;
364 if (id < m_vecs.size())
365 v_dst = m_vecs[id].get();
366 // Skip linked vars --- they should be taken care of by the parent var.
367 if (v_dst && !v_dst->isLinked()) {
368 if (other.getData (id)) {
369 void* src_ptr = other.getData (id, other_size, other_size);
370 if (src_ptr) {
371 if (!v_dst->insertMove (pos, src_ptr, 0, other_size,
372 other))
373 nomove = false;
374 }
375 }
376 else {
377 const void* orig = v_dst->toPtr();
378 v_dst->shift (pos, other_size);
379 if (orig != v_dst->toPtr())
380 nomove = false;
381 }
382 }
383 }
384
385 // Add any new variables not present in the original container.
386 for (SG::auxid_t id : other.getAuxIDs()) {
387 if (!m_auxids.test(id) && !ignore.test(id))
388 {
389 if (r.isLinked (id)) continue;
390 if (other.getData (id)) {
391 void* src_ptr = other.getData (id, other_size, other_size);
392 if (src_ptr) {
393 size_t sz = size_noLock();
394 if (sz < other_size) sz = other_size + pos;
395 IAuxTypeVector* v = getVectorInternal_noLock (id, sz, sz, false);
396 v->resize (sz - other_size);
397 (void)v->insertMove (pos, src_ptr, 0, other_size,
398 other);
399 nomove = false;
400 }
401 }
402 }
403 }
404
405 return nomove;
406}
407
408
416const SG::auxid_set_t&
417AuxStoreInternal::getAuxIDs() const
418{
419 return m_auxids;
420}
421
422
426const SG::auxid_set_t&
427AuxStoreInternal::getDecorIDs() const
428{
429 return m_decorations;
430}
431
432
438SG::auxid_set_t AuxStoreInternal::getCopyIDs (bool warnUnlocked) const
439{
440 return SG::getCopyIDs (m_auxids, m_decorations, warnUnlocked, {});
441}
442
443
448bool AuxStoreInternal::isDecoration (auxid_t auxid) const
449{
450 return m_decorations.test (auxid);
451}
452
453
460const SG::auxid_set_t&
461AuxStoreInternal::getWritableAuxIDs() const
462{
463 return getAuxIDs();
464}
465
466
478const void* AuxStoreInternal::getIODataInternal (auxid_t auxid, bool quiet) const
479{
480 guard_t guard (m_mutex);
481 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
482 if (!quiet) {
483 std::ostringstream ss;
484 ss << "Requested variable "
486 << " (" << auxid << ") doesn't exist";
487 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal", ss.str());
488 }
489 return 0;
490 }
491
492 if (m_standalone) {
493 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
494 return m_vecs[auxid]->toPtr();
495 }
496 return m_vecs[auxid]->toVector();
497}
498
499
511void* AuxStoreInternal::getIODataInternal (auxid_t auxid, bool quiet)
512{
513 guard_t guard (m_mutex);
514 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
515 if (!quiet) {
516 std::ostringstream ss;
517 ss << "Requested variable "
519 << " (" << auxid << ") doesn't exist";
520 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal", ss.str());
521 }
522 return 0;
523 }
524
525 if (m_standalone) {
526 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
527 return m_vecs[auxid]->toPtr();
528 }
529 return m_vecs[auxid]->toVector();
530}
531
532
543const void* AuxStoreInternal::getIOData (auxid_t auxid) const
544{
545 return getIODataInternal (auxid, false);
546}
547
548
560const std::type_info* AuxStoreInternal::getIOType (auxid_t auxid) const
561{
562 if (m_standalone) {
564 if (!r.isLinked (auxid))
565 return r.getType (auxid);
566 }
567 guard_t guard (m_mutex);
568 if (auxid < m_vecs.size() && m_vecs[auxid]) {
569 const std::type_info* ret = m_vecs[auxid]->objType();
570 if (ret) return ret;
571 }
573}
574
575
579const SG::auxid_set_t&
580AuxStoreInternal::getDynamicAuxIDs() const
581{
582 return getAuxIDs();
583}
584
585
592void AuxStoreInternal::lock()
593{
594 guard_t guard (m_mutex);
595 m_locked = true;
596}
597
598
609bool AuxStoreInternal::clearDecorations()
610{
611 guard_t guard (m_mutex);
612 bool anycleared = false;
613 for (auxid_t id : m_decorations) {
614 m_vecs[id].reset();
615 m_auxids.erase (id);
616 anycleared = true;
617 }
618 if (anycleared) {
619 m_decorations.clear();
620 }
621 return anycleared;
622}
623
624
630size_t AuxStoreInternal::size() const
631{
632 guard_t guard (m_mutex);
633 return size_noLock();
634}
635
636
642size_t AuxStoreInternal::size_noLock() const
643{
644 for (SG::auxid_t id : m_auxids) {
645 if (id < m_vecs.size() && m_vecs[id] && !m_vecs[id]->isLinked() &&
646 m_vecs[id]->size() > 0)
647 {
648 return m_vecs[id]->size();
649 }
650 }
651 return 0;
652}
653
654
664bool AuxStoreInternal::setOption (auxid_t id, const AuxDataOption& option)
665{
666 // Does this variable exist in this store?
667 bool exists = false;
668 {
669 guard_t guard (m_mutex);
670 if (id < m_vecs.size() && m_vecs[id] != 0)
671 exists = true;
672 }
673
674 // If not, and we have a packing parameter request, then create the variable.
675 if (!exists) {
676 if (!PackedParameters::isValidOption (option)) return false;
677 size_t sz = size();
678 getDataInternal (id, sz, sz, true);
679 }
680
681 // Try the option setting.
682 guard_t guard (m_mutex);
683 if (m_vecs[id]->setOption (option)) return true;
684
685 // It didn't work. If this is a packing request, then try to convert
686 // the variable to packed form and retry.
687 if (!PackedParameters::isValidOption (option)) return false;
688 std::unique_ptr<IAuxTypeVector> packed = m_vecs[id]->toPacked();
689 if (packed) {
690 // Converted to packed form. Replace the object and retry.
691 m_vecs[id] = std::move (packed);
692 return m_vecs[id]->setOption (option);
693 }
694
695 // Didn't work.
696 return false;
697}
698
699
704void AuxStoreInternal::addAuxID (auxid_t auxid)
705{
706 m_auxids.insert (auxid);
707}
708
709
711IAuxTypeVector*
712AuxStoreInternal::getVectorInternal_noLock (auxid_t auxid,
713 size_t size,
714 size_t capacity,
715 bool no_lock_check)
716{
717 if (m_vecs.size() <= auxid) {
718 m_vecs.resize (auxid+1);
719 }
720 if (m_vecs[auxid] == 0) {
721 if (m_locked && !no_lock_check)
722 throw ExcStoreLocked (auxid);
724 m_vecs[auxid] = r.makeVector (auxid, size, capacity);
725 addAuxID (auxid);
726 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
727 if (linked) {
728 auxid_t linked_id = linked->auxid();
729 m_vecs[linked_id] = std::move (linked);
730 addAuxID (linked_id);
731 }
732 }
733 else {
734 // Make sure the vector has at least the requested size.
735 // One way in which it could be short: setOption was called and created
736 // a variable in a store that had no other variables.
737 if (m_vecs[auxid]->size() < size) {
738 m_vecs[auxid]->resize (size);
739 m_vecs[auxid]->reserve (capacity);
740 }
741 }
742 return m_vecs[auxid].get();
743}
744
745
763void* AuxStoreInternal::getDataInternal (auxid_t auxid,
764 size_t size,
765 size_t capacity,
766 bool no_lock_check)
767{
768 guard_t guard (m_mutex);
769 return getVectorInternal_noLock (auxid, size, capacity, no_lock_check)->toPtr();
770}
771
772
781void AuxStoreInternal::lockDecoration (SG::auxid_t auxid)
782{
783 guard_t guard (m_mutex);
784 m_decorations.reset (auxid);
785}
786
787
797IAuxTypeVector* AuxStoreInternal::linkedVector (SG::auxid_t auxid)
798{
799 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
800 auxid_t linked_id = r.linkedVariable (auxid);
801 guard_t guard (m_mutex);
802 if (linked_id < m_vecs.size())
803 return m_vecs[linked_id].get();
804 return nullptr;
805}
806
807
817const IAuxTypeVector* AuxStoreInternal::linkedVector (SG::auxid_t auxid) const
818{
819 const AuxTypeRegistry& r = AuxTypeRegistry::instance();
820 auxid_t linked_id = r.linkedVariable (auxid);
821 guard_t guard (m_mutex);
822 if (linked_id < m_vecs.size())
823 return m_vecs[linked_id].get();
824 return nullptr;
825}
826
827
839 const SG::auxid_set_t& decors,
840 [[maybe_unused]] bool warnUnlocked,
841 [[maybe_unused]] std::span<const std::string> noWarn)
842{
843 SG::auxid_set_t out = auxids;
844#ifndef XAOD_STANDALONE
845 if (warnUnlocked) {
847 for (SG::auxid_t decor : decors) {
848 if (out.test (decor)) {
849 out.reset (decor);
850 if (std::ranges::find (noWarn, r.getName (decor)) == noWarn.end()) {
851 std::ostringstream ss;
852 ss << "skipped unlocked decoration during copy " << r.getName(decor)
853 << " (" << decor << ")";
854 ATHCONTAINERS_WARNING("getCopyAuxIDs", ss.str());
855 }
856 }
857 }
858 }
859 else
860#endif
861 out -= decors;
862 return out;
863}
864
865
866} // 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
static Double_t ss
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.
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.
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_WARNING(ctx, msg)
Definition error.h:57
#define ATHCONTAINERS_ERROR(ctx, msg)
Definition error.h:54
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?
AuxStoreInternal(bool standalone=false)
An auxiliary data store that holds data internally.
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