ATLAS Offline Software
Loading...
Searching...
No Matches
AuxStoreInternal.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
10
11
12#include <iostream>
13#include <sstream>
14#include <atomic>
15
21
22
23namespace SG {
24
25
35
36
45
46
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
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
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
145void
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
181
203void*
204AuxStoreInternal::getDecoration (auxid_t auxid, size_t size, size_t capacity)
205{
206 guard_t guard (m_mutex);
207 if (m_vecs.size() <= auxid) {
208 m_vecs.resize (auxid+1);
209 }
210 if (m_vecs[auxid] == 0) {
211 m_vecs[auxid] = AuxTypeRegistry::instance().makeVector (auxid, size, capacity);
212 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
213 auxid_t linked_id = null_auxid;
214 if (linked) {
215 linked_id = linked->auxid();
216 m_vecs[linked_id] = std::move (linked);
217 }
218 if (m_locked) {
219 // Need to be sure that the addition to the decoration bitset is visible
220 // to other threads before the addition to the variable bitset.
221 m_decorations.insert (auxid);
222 if (linked_id != null_auxid) {
223 m_decorations.insert (linked_id);
224 }
225 std::atomic_thread_fence (std::memory_order_seq_cst);
226 }
227 addAuxID (auxid);
228 if (linked_id != null_auxid) {
229 addAuxID (linked_id);
230 }
231 }
232 if (m_locked && !m_decorations.test (auxid)) {
233 throw ExcStoreLocked (auxid);
234 }
235 return m_vecs[auxid]->toPtr();
236}
237
238
255{
256 guard_t guard (m_mutex);
257 if (m_locked)
258 throw ExcStoreLocked ("resize");
259 bool nomoves = true;
260 for (SG::auxid_t id : m_auxids) {
261 SG::IAuxTypeVector* v = nullptr;
262 if (id < m_vecs.size())
263 v = m_vecs[id].get();
264 if (v && !v->isLinked()) {
265 if (!v->resize (sz))
266 nomoves = false;
267 }
268 }
269 return nomoves;
270}
271
272
282{
283 guard_t guard (m_mutex);
284 if (m_locked)
285 throw ExcStoreLocked ("reserve");
286 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
287 if (v && !v->isLinked())
288 v->reserve (sz);
289 }
290}
291
292
315void AuxStoreInternal::shift (size_t pos, ptrdiff_t offs)
316{
317 guard_t guard (m_mutex);
318 if (m_locked)
319 throw ExcStoreLocked ("shift");
320 for (std::unique_ptr<IAuxTypeVector>& v : m_vecs) {
321 if (v && !v->isLinked())
322 v->shift (pos, offs);
323 }
324}
325
326
347 IAuxStore& other,
348 const SG::auxid_set_t& ignore)
349{
350 guard_t guard (m_mutex);
352
353 if (m_locked)
354 throw ExcStoreLocked ("insertMove");
355 bool nomove = true;
356 size_t other_size = other.size();
357 if (other_size == 0)
358 return true;
359 for (SG::auxid_t id : m_auxids) {
360 SG::IAuxTypeVector* v_dst = nullptr;
361 if (id < m_vecs.size())
362 v_dst = m_vecs[id].get();
363 // Skip linked vars --- they should be taken care of by the parent var.
364 if (v_dst && !v_dst->isLinked()) {
365 if (other.getData (id)) {
366 void* src_ptr = other.getData (id, other_size, other_size);
367 if (src_ptr) {
368 if (!v_dst->insertMove (pos, src_ptr, 0, other_size,
369 other))
370 nomove = false;
371 }
372 }
373 else {
374 const void* orig = v_dst->toPtr();
375 v_dst->shift (pos, other_size);
376 if (orig != v_dst->toPtr())
377 nomove = false;
378 }
379 }
380 }
381
382 // Add any new variables not present in the original container.
383 for (SG::auxid_t id : other.getAuxIDs()) {
384 if (!m_auxids.test(id) && !ignore.test(id))
385 {
386 if (r.isLinked (id)) continue;
387 if (other.getData (id)) {
388 void* src_ptr = other.getData (id, other_size, other_size);
389 if (src_ptr) {
390 size_t sz = size_noLock();
391 if (sz < other_size) sz = other_size + pos;
392 IAuxTypeVector* v = getVectorInternal_noLock (id, sz, sz, false);
393 v->resize (sz - other_size);
394 (void)v->insertMove (pos, src_ptr, 0, other_size,
395 other);
396 nomove = false;
397 }
398 }
399 }
400 }
401
402 return nomove;
403}
404
405
413const SG::auxid_set_t&
415{
416 return m_auxids;
417}
418
419
423const SG::auxid_set_t&
425{
426 return m_decorations;
427}
428
435{
436 return m_decorations.test (auxid);
437}
438
439
446const SG::auxid_set_t&
448{
449 return getAuxIDs();
450}
451
452
464const void* AuxStoreInternal::getIODataInternal (auxid_t auxid, bool quiet) const
465{
466 guard_t guard (m_mutex);
467 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
468 if (!quiet) {
469 std::ostringstream ss;
470 ss << "Requested variable "
472 << " (" << auxid << ") doesn't exist";
473 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal", ss.str());
474 }
475 return 0;
476 }
477
478 if (m_standalone) {
479 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
480 return m_vecs[auxid]->toPtr();
481 }
482 return m_vecs[auxid]->toVector();
483}
484
485
498{
499 guard_t guard (m_mutex);
500 if (auxid >= m_vecs.size() || !m_vecs[auxid]) {
501 if (!quiet) {
502 std::ostringstream ss;
503 ss << "Requested variable "
505 << " (" << auxid << ") doesn't exist";
506 ATHCONTAINERS_ERROR("AuxStoreInternal::getIODataInternal", ss.str());
507 }
508 return 0;
509 }
510
511 if (m_standalone) {
512 if (!SG::AuxTypeRegistry::instance().isLinked (auxid))
513 return m_vecs[auxid]->toPtr();
514 }
515 return m_vecs[auxid]->toVector();
516}
517
518
529const void* AuxStoreInternal::getIOData (auxid_t auxid) const
530{
531 return getIODataInternal (auxid, false);
532}
533
534
546const std::type_info* AuxStoreInternal::getIOType (auxid_t auxid) const
547{
548 if (m_standalone) {
550 if (!r.isLinked (auxid))
551 return r.getType (auxid);
552 }
553 guard_t guard (m_mutex);
554 if (auxid < m_vecs.size() && m_vecs[auxid]) {
555 const std::type_info* ret = m_vecs[auxid]->objType();
556 if (ret) return ret;
557 }
559}
560
561
565const SG::auxid_set_t&
567{
568 return getAuxIDs();
569}
570
571
579{
580 guard_t guard (m_mutex);
581 m_locked = true;
582}
583
584
596{
597 guard_t guard (m_mutex);
598 bool anycleared = false;
599 for (auxid_t id : m_decorations) {
600 m_vecs[id].reset();
601 m_auxids.erase (id);
602 anycleared = true;
603 }
604 if (anycleared) {
605 m_decorations.clear();
606 }
607 return anycleared;
608}
609
610
617{
618 guard_t guard (m_mutex);
619 return size_noLock();
620}
621
622
629{
630 for (SG::auxid_t id : m_auxids) {
631 if (id < m_vecs.size() && m_vecs[id] && !m_vecs[id]->isLinked() &&
632 m_vecs[id]->size() > 0)
633 {
634 return m_vecs[id]->size();
635 }
636 }
637 return 0;
638}
639
640
651{
652 // Does this variable exist in this store?
653 bool exists = false;
654 {
655 guard_t guard (m_mutex);
656 if (id < m_vecs.size() && m_vecs[id] != 0)
657 exists = true;
658 }
659
660 // If not, and we have a packing parameter request, then create the variable.
661 if (!exists) {
662 if (!PackedParameters::isValidOption (option)) return false;
663 size_t sz = size();
664 getDataInternal (id, sz, sz, true);
665 }
666
667 // Try the option setting.
668 guard_t guard (m_mutex);
669 if (m_vecs[id]->setOption (option)) return true;
670
671 // It didn't work. If this is a packing request, then try to convert
672 // the variable to packed form and retry.
673 if (!PackedParameters::isValidOption (option)) return false;
674 std::unique_ptr<IAuxTypeVector> packed = m_vecs[id]->toPacked();
675 if (packed) {
676 // Converted to packed form. Replace the object and retry.
677 m_vecs[id] = std::move (packed);
678 return m_vecs[id]->setOption (option);
679 }
680
681 // Didn't work.
682 return false;
683}
684
685
691{
692 m_auxids.insert (auxid);
693}
694
695
699 size_t size,
700 size_t capacity,
701 bool no_lock_check)
702{
703 if (m_vecs.size() <= auxid) {
704 m_vecs.resize (auxid+1);
705 }
706 if (m_vecs[auxid] == 0) {
707 if (m_locked && !no_lock_check)
708 throw ExcStoreLocked (auxid);
710 m_vecs[auxid] = r.makeVector (auxid, size, capacity);
711 addAuxID (auxid);
712 std::unique_ptr<IAuxTypeVector> linked = m_vecs[auxid]->linkedVector();
713 if (linked) {
714 auxid_t linked_id = linked->auxid();
715 m_vecs[linked_id] = std::move (linked);
716 addAuxID (linked_id);
717 }
718 }
719 else {
720 // Make sure the vector has at least the requested size.
721 // One way in which it could be short: setOption was called and created
722 // a variable in a store that had no other variables.
723 if (m_vecs[auxid]->size() < size) {
724 m_vecs[auxid]->resize (size);
725 m_vecs[auxid]->reserve (capacity);
726 }
727 }
728 return m_vecs[auxid].get();
729}
730
731
750 size_t size,
751 size_t capacity,
752 bool no_lock_check)
753{
754 guard_t guard (m_mutex);
755 return getVectorInternal_noLock (auxid, size, capacity, no_lock_check)->toPtr();
756}
757
758
768{
769 guard_t guard (m_mutex);
770 m_decorations.reset (auxid);
771}
772
773
784{
786 auxid_t linked_id = r.linkedVariable (auxid);
787 guard_t guard (m_mutex);
788 if (linked_id < m_vecs.size())
789 return m_vecs[linked_id].get();
790 return nullptr;
791}
792
793
804{
806 auxid_t linked_id = r.linkedVariable (auxid);
807 guard_t guard (m_mutex);
808 if (linked_id < m_vecs.size())
809 return m_vecs[linked_id].get();
810 return nullptr;
811}
812
813
814} // 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.
static Double_t sz
static Double_t ss
Describe how the contents of a PackedContainer are to be saved.
Hold information about an option setting request.
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.
virtual bool setOption(auxid_t id, const AuxDataOption &option) override
Set an option for an auxiliary data variable.
bool standalone() const
Return the standalone flag.
bool m_locked
Has this container been locked?
virtual const void * getData(SG::auxid_t auxid) const override
Return the data vector for one aux data item.
virtual const std::type_info * getIOType(SG::auxid_t auxid) const override
Return the type of the data to be stored for one aux data item.
virtual IAuxTypeVector * getVectorInternal_noLock(SG::auxid_t auxid, size_t size, size_t capacity, bool no_lock_check)
Implementation of getVectorInternal; no locking.
const void * getIODataInternal(auxid_t auxid, bool quiet) const
Return a pointer to the data to be stored for one aux data item.
virtual const SG::auxid_set_t & getDynamicAuxIDs() const override
Get the list of all variables that need to be handled.
virtual bool resize(size_t sz) override
Change the size of all aux data vectors.
std::vector< std::unique_ptr< IAuxTypeVector > > m_vecs
The collection of vectors of aux data that we're managing, indexed by auxid.
virtual void lockDecoration(SG::auxid_t auxid) override
Lock a decoration.
SG::auxid_set_t m_decorations
Record which variables are decorations.
virtual const SG::auxid_set_t & getAuxIDs() const override
Return a set of identifiers for existing data items in this store.
virtual bool isDecoration(auxid_t auxid) const override
Test if a particular variable is tagged as a decoration.
SG::auxid_set_t m_auxids
Set of auxid's for which we've created a vector.
virtual const SG::auxid_set_t & getWritableAuxIDs() const override
Return a set of identifiers for writable data items in this store.
void addVector(std::unique_ptr< IAuxTypeVector > vec, bool isDecoration)
Explicitly add a vector to the store.
virtual const IAuxTypeVector * getVector(SG::auxid_t auxid) const override
Return vector interface for one aux data item.
size_t size_noLock() const
Return the number of elements in the store; no locking.
virtual bool insertMove(size_t pos, IAuxStore &other, const SG::auxid_set_t &ignore=SG::auxid_set_t(0)) override
Move all elements from other to this store.
virtual size_t size() const override
Return the number of elements in the store.
virtual ~AuxStoreInternal()
Destructor.
virtual const SG::auxid_set_t & getDecorIDs() const override
Return a set of identifiers for decorations in this store.
virtual void reserve(size_t sz) override
Change the capacity of all aux data vectors.
virtual bool clearDecorations() override
Clear all decorations.
virtual void * getDecoration(auxid_t auxid, size_t size, size_t capacity) override
Return the data vector for one aux data decoration item.
virtual void lock() override
Lock the container.
AuxStoreInternal(bool standalone=false)
Constructor.
virtual IAuxTypeVector * linkedVector(SG::auxid_t auxid) override
Return interface for a linked variable.
void addAuxID(auxid_t auxid)
Add a new auxid to the set of those being managed by this store.
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the container.
virtual const void * getIOData(SG::auxid_t auxid) const override
Return a pointer to the data to be stored for one aux data item.
bool m_standalone
Are we being written in standalone mode?
AthContainers_detail::lock_guard< mutex_t > guard_t
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.
std::unique_ptr< IAuxTypeVector > makeVector(SG::auxid_t auxid, size_t size, size_t capacity) const
Construct a new vector to hold an aux item.
Exception — Attempted to modify auxiliary data in a locked store.
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.
static bool isValidOption(const AuxDataOption &option)
Test to see if option is a recognized packing option.
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:54
int r
Definition globals.cxx:22
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