ATLAS Offline Software
Loading...
Searching...
No Matches
AuxVectorData.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
19#include <sstream>
20
21
22namespace SG {
23
24
26size_t AuxVectorData::s_minCacheLen = 1024;
27
28
30const SG::auxid_set_t AuxVectorData::s_emptySet(0);
31
32
41
42
48 : m_cache (std::move (rhs.m_cache)),
49 m_constCache (std::move (rhs.m_constCache)),
50 m_decorCache (std::move (rhs.m_decorCache)),
51 m_spanCache (std::move (rhs.m_spanCache)),
52 m_store (rhs.m_store),
55{
56 rhs.m_store = 0;
57 rhs.m_constStore = 0;
58 rhs.m_constStoreLink.clear();
59}
60
61
67{
68 if (this != &rhs) {
69 m_cache = std::move (rhs.m_cache);
70 m_constCache = std::move (rhs.m_constCache);
71 m_decorCache = std::move (rhs.m_decorCache);
72 m_spanCache = std::move (rhs.m_spanCache);
73 m_store = rhs.m_store;
74 m_constStore = rhs.m_constStore;
75 m_constStoreLink = rhs.m_constStoreLink;
76
77 rhs.m_store = 0;
78 rhs.m_constStore = 0;
79 rhs.m_constStoreLink.clear();
80 }
81 return *this;
82}
83
84
91
92
100void AuxVectorData::setStore (const SG::IConstAuxStore* store)
101{
102 m_store = 0;
103 m_constStore = store;
104 m_constStoreLink.clear();
105 clearCache();
106}
107
108
117{
118 m_store = store;
119 m_constStore = store;
120 m_constStoreLink.clear();
121 clearCache();
122}
123
124
133{
134 m_store = 0;
135 m_constStore = 0;
136 m_constStoreLink = store;
137 clearCache();
138}
139
140
151{
152 if (id == null_auxid) return false;
153 SG::IAuxStore* store = getStore();
154 if (!store) return false;
155 return store->setOption (id, option);
156}
157
158
168bool AuxVectorData::setOption (const std::string& name,
169 const AuxDataOption& option)
170{
172 return setOption (id, option);
173}
174
175
186bool AuxVectorData::setOption (const std::string& name,
187 const std::string& clsname,
188 const AuxDataOption& option)
189{
190 auxid_t id = SG::AuxTypeRegistry::instance().findAuxID (name, clsname);
191 return setOption (id, option);
192}
193
194
204{
205 const SG::IConstAuxStore* store = getConstStore();
206 if (store)
207 return store->getAuxIDs();
208 return s_emptySet;
209}
210
211
220SG::auxid_set_t AuxVectorData::getCopyIDs (bool warnUnlocked /*= false*/) const
221{
222 const SG::IConstAuxStore* store = getConstStore();
223 if (store)
224 return store->getCopyIDs (warnUnlocked);
225 return SG::auxid_set_t();
226}
227
228
233{
234 if (getConstStore())
235 return getConstStore()->getDecorIDs();
236 return s_emptySet;
237}
238
239
249{
250 if (m_store)
251 return m_store->getWritableAuxIDs();
252 return s_emptySet;
253}
254
255
261{
262 guard_t guard (m_mutex);
263
264 const SG::IConstAuxStore* store = getConstStore();
265 if (!store) return false;
266
267 // Don't rely on getAuxIDs() --- the store can lie.
268 // Explicitly try to fetch the data.
269 const void* ptr = store->getData (id);
270 if (ptr) {
271 // We could avoid the const_cast here by having distinct const and
272 // non-const Cache types, holding const void* and void*, respectively.
273 // However, since this is a purely internal class that users don't
274 // deal with directly, that's not worth the bother (and the extra code).
275 void* vp ATLAS_THREAD_SAFE = const_cast<void*> (ptr);
276 m_constCache.store (id, vp);
277 return true;
278 }
279 return false;
280}
281
282
288{
289 const SG::IAuxStore* store = getStore();
290 if (!store) return false;
291 return store->getWritableAuxIDs().test(id);
292}
293
294
300{
301 if (!isAvailableOol (id)) return false;
302
303 // Not nice, but not sure we can do otherwise without changing interfaces.
304 // I think the case of a caught exception should be rare.
305 try {
306 this->getDecorationArray (id);
307 }
308 catch (const SG::ExcStoreLocked&) {
309 return false;
310 }
311 return true;
312}
313
314
326{
327 guard_t guard (m_mutex);
328
329 // Fetch the pointer from the store, or raise an exception if we don't
330 // have a non-const store.
331 void* ptr = 0;
332 if (m_store) {
333 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
334 ptr = m_store->getData (auxid, 0, 0);
335 }
336 else {
337 ptr = m_store->getData (auxid, this->size_v(), this->capacity_v());
338 }
339 }
340 else if (getConstStore())
341 throw SG::ExcConstAuxData ("fetch item", auxid);
342 else
343 throw SG::ExcNoAuxStore (auxid);
344
345 // Check that we got a good pointer back, otherwise throw.
346 if (ptr) {
347 m_cache.store (auxid, ptr);
348
349 // Set the same entry in the other caches as well.
350 m_constCache.store (auxid, ptr);
351 m_decorCache.store (auxid, ptr);
352 }
353 else if (!allowMissing)
354 throw SG::ExcBadAuxVar (auxid);
355
356 return ptr;
357}
358
359
371 bool allowMissing) const
372{
373 guard_t guard (m_mutex);
374
375 // Fetch the pointer from the store, or raise an exception if we don't
376 // have a const store.
377 const void* ptr = 0;
378 const SG::IConstAuxStore* store = getConstStore();
379 if (store)
380 ptr = store->getData (auxid);
381 else
382 throw SG::ExcNoAuxStore (auxid);
383
384 // Check that we got a good pointer back, otherwise throw.
385 if (ptr) {
386 // We could avoid the const_cast here by having distinct const and
387 // non-const Cache types, holding const void* and void*, respectively.
388 // However, since this is a purely internal class that users don't
389 // deal with directly, that's not worth the bother (and the extra code).
390 void* vp ATLAS_THREAD_SAFE = const_cast<void*> (ptr);
391 m_constCache.store (auxid, vp);
392 }
393 else if (!allowMissing)
394 throw SG::ExcBadAuxVar (auxid);
395
396 return ptr;
397}
398
399
415{
416 guard_t guard (m_mutex);
417
418 // Fetch the pointer from the store, or raise an exception if we don't
419 // have a non-const store.
420 void* ptr = 0;
421 if (m_store) {
422 // Avoid warning about calling non-const function. OK here.
424 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
425 ptr = store->getDecoration (auxid, 0, 0);
426 }
427 else {
428 ptr = store->getDecoration (auxid, this->size_v(), this->capacity_v());
429 }
430 }
431 else if (getConstStore()) {
432 // The whole point of decorations is to allow adding information to
433 // something that's otherwise const. So we have the const_cast here.
434 // The store object is responsible for determining whether the
435 // modification is really allowed or not.
436 IConstAuxStore* store ATLAS_THREAD_SAFE =
437 const_cast<IConstAuxStore*> (getConstStore());
438 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
439 ptr = store->getDecoration (auxid, 0, 0);
440 }
441 else {
442 ptr = store->getDecoration (auxid, this->size_v(), this->capacity_v());
443 }
444 }
445 else
446 throw SG::ExcNoAuxStore (auxid);
447
448 // Check that we got a good pointer back, otherwise throw.
449 if (!ptr)
450 throw SG::ExcBadAuxVar (auxid);
451
452 m_decorCache.store (auxid, ptr);
453
454 // Set the same entry in the const cache as well.
455 m_constCache.store (auxid, ptr);
456
457 return ptr;
458}
459
460
472const AuxDataSpanBase*
474{
475 guard_t guard (m_mutex);
476
477 // Fetch the pointer from the store, or raise an exception if we don't
478 // have a const store.
479 const IAuxTypeVector* v = 0;
480 const SG::IConstAuxStore* store = getConstStore();
481 if (store)
482 v = store->getVector (auxid);
483 else
484 throw SG::ExcNoAuxStore (auxid);
485
486 // Check that we got a good pointer back, otherwise throw.
487 const AuxDataSpanBase* ptr = nullptr;
488 if (v) {
489 ptr = &v->getDataSpan();
490 // We could avoid the const_cast here by having distinct const and
491 // non-const Cache types, holding const void* and void*, respectively.
492 // However, since this is a purely internal class that users don't
493 // deal with directly, that's not worth the bother (and the extra code).
494 AuxDataSpanBase* vp ATLAS_THREAD_SAFE = const_cast<AuxDataSpanBase*> (ptr);
495 m_spanCache.store (auxid, vp);
496 }
497 else if (!allowMissing)
498 throw SG::ExcBadAuxVar (auxid);
499
500 return ptr;
501}
502
503
512
513
519 : m_cache_len (rhs.m_cache_len),
520 m_allcache (std::move (rhs.m_allcache))
521{
522 m_cache[0] = rhs.m_cache[0];
523 m_cache[1] = rhs.m_cache[1];
524 rhs.m_cache[0] = 0;
525 rhs.m_cache[1] = 0;
526 rhs.m_cache_len = 0;
527}
528
529
535{
536 if (this != &rhs) {
537 clear();
538 m_cache_len = rhs.m_cache_len;
539 m_allcache = std::move (rhs.m_allcache);
540
541 m_cache[0] = rhs.m_cache[0];
542 m_cache[1] = rhs.m_cache[1];
543 rhs.m_cache[0] = 0;
544 rhs.m_cache[1] = 0;
545 rhs.m_cache_len = 0;
546 }
547 return *this;
548}
549
550
555{
556 for (size_t i=0; i < m_allcache.size(); i++) delete [] m_allcache[i];
557}
558
559
565{
566 m_allcache.swap (other.m_allcache);
567 std::swap (m_cache, other.m_cache);
568 std::swap (m_cache_len, other.m_cache_len);
569}
570
571
576{
577 if (m_cache_len > 0) {
578 if (m_allcache.size() > 1) {
579 for (size_t i=0; i < m_allcache.size()-1; i++)
580 delete [] m_allcache[i];
581 m_allcache[0] = m_allcache.back();
582 m_allcache.resize(1);
583 }
584 std::fill (m_cache[0], m_cache[0] + m_cache_len, static_cast<void*>(0));
585 }
586}
587
588
597{
598 if (auxid < m_cache_len) {
599 m_cache[0][auxid] = nullptr;
600 }
601}
602
603
610{
611 // We must be holding the container lock m_mutex to call this.
612
613 if (auxid >= m_cache_len) {
614 // We need to expand the cache vector. Allocate a new one.
615 size_t newlen =
616 std::max (static_cast<SG::auxid_t>(AuxVectorData::s_minCacheLen),
617 (auxid+1)*3/2);
618 void** newcache = new void*[newlen];
619 m_allcache.push_back (newcache);
620 void** oldcache = m_cache[0];
621
622 // Copy old vector to the new one and clear the remainder.
623 std::copy (oldcache, oldcache + m_cache_len, newcache);
624 std::fill (newcache + m_cache_len, newcache + newlen,
625 static_cast<void*>(0));
626
627 // The above writes must be visible before we update the cache pointers.
629
630 // Store so that other threads can see it.
631 // The stores to m_cache must happen before the store to m_cache_len;
632 // we use a fence to ensure this.
633 m_cache[0] = newcache;
634 m_cache[1] = newcache;
636 m_cache_len = newlen;
637 }
638
639 // We have room in the cache vector now. Store the pointer.
640 m_cache[0][auxid] = ptr;
641}
642
643
651{
652 if (m_store) {
653 m_store->lock();
654 clearCache();
655 }
656
657 // No error if no store or no writable store.
658}
659
660
671{
672 bool ret = false;
673 if (m_store) {
674 // Avoid warning about calling non-const function. OK here.
676 ret = store->clearDecorations();
677 m_cache.clear();
678 m_constCache.clear();
679 m_decorCache.clear();
680 }
681 else if (getConstStore()) {
682 // The whole point of decorations is to allow adding information to
683 // something that's otherwise const. So we have the const_cast here.
684 // The store object is responsible for determining whether the
685 // modification is really allowed or not.
686 IConstAuxStore* store ATLAS_THREAD_SAFE =
687 const_cast<IConstAuxStore*> (getConstStore());
688 ret = store->clearDecorations();
689 }
690 else
691 throw SG::ExcNoAuxStore ("lock");
692 return ret;
693}
694
695
705{
706 const IConstAuxStore* store = this->getConstStore();
707 if (store) {
708 // Casting away const ok if no other thread is accessing this decoration.
709 IConstAuxStore* store_nc ATLAS_THREAD_SAFE = const_cast<IConstAuxStore*> (store);
710 store_nc->lockDecoration (auxid);
711 this->clearDecorCache (auxid);
712 }
713}
714
715
721const SG::IConstAuxStore* AuxVectorData::getConstStoreOol() const
722{
723 return getConstStore();
724}
725
726
727
728} // namespace SG
Handle mappings between names and auxid_t.
Manage lookup of vectors of auxiliary data.
Exceptions that can be thrown from AthContainers.
Interface for non-const operations on an auxiliary store.
Interface for const operations on an auxiliary store.
void clear()
Empty the pool.
Define macros for attributes used to control the static checker.
Hold information about an option setting request.
SG::auxid_t findAuxID(const std::string &name, const std::string &clsname="") const
Look up a name -> auxid_t mapping.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Manage cache of pointers to aux element vectors.
void ** m_cache[2]
Pointer to the cache vector.
std::vector< void ** > m_allcache
All cache vectors that have been allocated.
size_t m_cache_len
Length of the cache vector.
void swap(Cache &other)
Swap this cache object with another.
Cache()
Cache manager constructor.
Cache & operator=(Cache &&rhs)
Cache manager move assignment.
void clear()
Clear the cache (and free any old cache vectors).
void store(SG::auxid_t auxid, void *ptr)
Store a pointer for auxid in the cache.
~Cache()
Cache manager destructor.
bool clearDecorations() const
Clear all decorations.
const SG::auxid_set_t & getAuxIDs() const
Return a set of identifiers for existing data items in store associated with this object.
const AuxDataSpanBase * getDataSpanOol(SG::auxid_t auxid, bool allowMissing) const
Return a reference to a description of this vector's start+size, out-of-line portion.
bool isAvailableOol(auxid_t id) const
Out-of-line portion of isAvailable.
const SG::IConstAuxStore * getConstStoreOol() const
Same as getConstStore.
SG::auxid_set_t getCopyIDs(bool warnUnlocked=false) const
Return the set of variables to copy in a deep copy.
static size_t s_minCacheLen ATLAS_THREAD_SAFE
Minimum length to use for the cache vector.
void setStore(SG::IAuxStore *store)
Set the store associated with this object.
const SG::auxid_set_t & getDecorIDs() const
Return a set of identifiers for decorations for this object.
DataLink< SG::IConstAuxStore > m_constStoreLink
Associated store link, const.
void * getDataOol(SG::auxid_t auxid, bool allowMissing)
Out-of-line portion of data access.
void * getDecorationArray(SG::auxid_t auxid) const
Return a pointer to the start of an aux data vector for a decoration.
void lockDecoration(SG::auxid_t auxid)
Explicitly lock a decoration.
AuxVectorData & operator=(AuxVectorData &&rhs)
Move assignment.
SG::IAuxStore * m_store
Associated store, non-const.
void clearDecorCache(SG::auxid_t auxid)
Clear the cached decoration pointer for a single variable.
void clearCache()
Clear the cached aux data pointers.
void * getDecorationOol(SG::auxid_t auxid) const
Out-of-line portion of data access (decorator version).
virtual size_t size_v() const =0
Return the size of the container.
static const SG::auxid_set_t s_emptySet
Empty auxid set, used for a return value when we have no associated store.
virtual size_t capacity_v() const =0
Return the capacity of the container.
AthContainers_detail::lock_guard< mutex_t > guard_t
const SG::IConstAuxStore * m_constStore
Associated store, const.
bool isAvailableWritableOol(auxid_t id)
Out-of-line portion of isAvailableWritable.
AuxVectorData()
Constructor.
bool isAvailableWritableAsDecorationOol(auxid_t id) const
Out-of-line portion of isAvailableWritableAsDecoration.
SG::IAuxStore * getStore()
Return the current store, as a non-const interface.
virtual ~AuxVectorData()
Destructor.
bool setOption(auxid_t id, const AuxDataOption &option)
Set an option for an auxiliary data variable.
const SG::auxid_set_t & getWritableAuxIDs() const
Return a set of identifiers for writable data items in this store.
const SG::IConstAuxStore * getConstStore() const
Return the current store, as a const interface.
virtual void lock() override
Lock the container.
Exception — Attempt to retrieve nonexistent aux data item.
Exception — Non-const operation performed on const aux data.
Exception — Aux data requested from object with no store.
Exception — Attempted to modify auxiliary data in a locked store.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:51
Abstract interface for manipulating vectors of arbitrary types.
A set of aux data identifiers.
Definition AuxTypes.h:47
Helper for emitting error messages.
void fence_seq_cst()
A sequentially-consistent fence.
Forward declaration.
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
SG::auxid_t auxid() const
Return the aux id for this variable.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
STL namespace.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Minimal span-like object describing the range of an auxiliary variable.
Definition AuxDataSpan.h:40