ATLAS Offline Software
Loading...
Searching...
No Matches
AuxVectorData.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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
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
216{
217 if (getConstStore())
218 return getConstStore()->getDecorIDs();
219 return s_emptySet;
220}
221
222
232{
233 if (m_store)
234 return m_store->getWritableAuxIDs();
235 return s_emptySet;
236}
237
238
244{
245 guard_t guard (m_mutex);
246
247 const SG::IConstAuxStore* store = getConstStore();
248 if (!store) return false;
249
250 // Don't rely on getAuxIDs() --- the store can lie.
251 // Explicitly try to fetch the data.
252 const void* ptr = store->getData (id);
253 if (ptr) {
254 // We could avoid the const_cast here by having distinct const and
255 // non-const Cache types, holding const void* and void*, respectively.
256 // However, since this is a purely internal class that users don't
257 // deal with directly, that's not worth the bother (and the extra code).
258 void* vp ATLAS_THREAD_SAFE = const_cast<void*> (ptr);
259 m_constCache.store (id, vp);
260 return true;
261 }
262 return false;
263}
264
265
271{
272 const SG::IAuxStore* store = getStore();
273 if (!store) return false;
274 return store->getWritableAuxIDs().test(id);
275}
276
277
283{
284 if (!isAvailableOol (id)) return false;
285
286 // Not nice, but not sure we can do otherwise without changing interfaces.
287 // I think the case of a caught exception should be rare.
288 try {
289 this->getDecorationArray (id);
290 }
291 catch (const SG::ExcStoreLocked&) {
292 return false;
293 }
294 return true;
295}
296
297
308void* AuxVectorData::getDataOol (SG::auxid_t auxid, bool allowMissing)
309{
310 guard_t guard (m_mutex);
311
312 // Fetch the pointer from the store, or raise an exception if we don't
313 // have a non-const store.
314 void* ptr = 0;
315 if (m_store) {
316 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
317 ptr = m_store->getData (auxid, 0, 0);
318 }
319 else {
320 ptr = m_store->getData (auxid, this->size_v(), this->capacity_v());
321 }
322 }
323 else if (getConstStore())
324 throw SG::ExcConstAuxData ("fetch item", auxid);
325 else
326 throw SG::ExcNoAuxStore (auxid);
327
328 // Check that we got a good pointer back, otherwise throw.
329 if (ptr) {
330 m_cache.store (auxid, ptr);
331
332 // Set the same entry in the other caches as well.
333 m_constCache.store (auxid, ptr);
334 m_decorCache.store (auxid, ptr);
335 }
336 else if (!allowMissing)
337 throw SG::ExcBadAuxVar (auxid);
338
339 return ptr;
340}
341
342
354 bool allowMissing) const
355{
356 guard_t guard (m_mutex);
357
358 // Fetch the pointer from the store, or raise an exception if we don't
359 // have a const store.
360 const void* ptr = 0;
361 const SG::IConstAuxStore* store = getConstStore();
362 if (store)
363 ptr = store->getData (auxid);
364 else
365 throw SG::ExcNoAuxStore (auxid);
366
367 // Check that we got a good pointer back, otherwise throw.
368 if (ptr) {
369 // We could avoid the const_cast here by having distinct const and
370 // non-const Cache types, holding const void* and void*, respectively.
371 // However, since this is a purely internal class that users don't
372 // deal with directly, that's not worth the bother (and the extra code).
373 void* vp ATLAS_THREAD_SAFE = const_cast<void*> (ptr);
374 m_constCache.store (auxid, vp);
375 }
376 else if (!allowMissing)
377 throw SG::ExcBadAuxVar (auxid);
378
379 return ptr;
380}
381
382
398{
399 guard_t guard (m_mutex);
400
401 // Fetch the pointer from the store, or raise an exception if we don't
402 // have a non-const store.
403 void* ptr = 0;
404 if (m_store) {
405 // Avoid warning about calling non-const function. OK here.
407 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
408 ptr = store->getDecoration (auxid, 0, 0);
409 }
410 else {
411 ptr = store->getDecoration (auxid, this->size_v(), this->capacity_v());
412 }
413 }
414 else if (getConstStore()) {
415 // The whole point of decorations is to allow adding information to
416 // something that's otherwise const. So we have the const_cast here.
417 // The store object is responsible for determining whether the
418 // modification is really allowed or not.
420 const_cast<IConstAuxStore*> (getConstStore());
421 if (SG::AuxTypeRegistry::instance().isLinked (auxid)) {
422 ptr = store->getDecoration (auxid, 0, 0);
423 }
424 else {
425 ptr = store->getDecoration (auxid, this->size_v(), this->capacity_v());
426 }
427 }
428 else
429 throw SG::ExcNoAuxStore (auxid);
430
431 // Check that we got a good pointer back, otherwise throw.
432 if (!ptr)
433 throw SG::ExcBadAuxVar (auxid);
434
435 m_decorCache.store (auxid, ptr);
436
437 // Set the same entry in the const cache as well.
438 m_constCache.store (auxid, ptr);
439
440 return ptr;
441}
442
443
455const AuxDataSpanBase*
456AuxVectorData::getDataSpanOol (SG::auxid_t auxid, bool allowMissing) const
457{
458 guard_t guard (m_mutex);
459
460 // Fetch the pointer from the store, or raise an exception if we don't
461 // have a const store.
462 const IAuxTypeVector* v = 0;
463 const SG::IConstAuxStore* store = getConstStore();
464 if (store)
465 v = store->getVector (auxid);
466 else
467 throw SG::ExcNoAuxStore (auxid);
468
469 // Check that we got a good pointer back, otherwise throw.
470 const AuxDataSpanBase* ptr = nullptr;
471 if (v) {
472 ptr = &v->getDataSpan();
473 // We could avoid the const_cast here by having distinct const and
474 // non-const Cache types, holding const void* and void*, respectively.
475 // However, since this is a purely internal class that users don't
476 // deal with directly, that's not worth the bother (and the extra code).
477 AuxDataSpanBase* vp ATLAS_THREAD_SAFE = const_cast<AuxDataSpanBase*> (ptr);
478 m_spanCache.store (auxid, vp);
479 }
480 else if (!allowMissing)
481 throw SG::ExcBadAuxVar (auxid);
482
483 return ptr;
484}
485
486
495
496
502 : m_cache_len (rhs.m_cache_len),
503 m_allcache (std::move (rhs.m_allcache))
504{
505 m_cache[0] = rhs.m_cache[0];
506 m_cache[1] = rhs.m_cache[1];
507 rhs.m_cache[0] = 0;
508 rhs.m_cache[1] = 0;
509 rhs.m_cache_len = 0;
510}
511
512
518{
519 if (this != &rhs) {
520 clear();
521 m_cache_len = rhs.m_cache_len;
522 m_allcache = std::move (rhs.m_allcache);
523
524 m_cache[0] = rhs.m_cache[0];
525 m_cache[1] = rhs.m_cache[1];
526 rhs.m_cache[0] = 0;
527 rhs.m_cache[1] = 0;
528 rhs.m_cache_len = 0;
529 }
530 return *this;
531}
532
533
538{
539 for (size_t i=0; i < m_allcache.size(); i++) delete [] m_allcache[i];
540}
541
542
548{
549 m_allcache.swap (other.m_allcache);
550 std::swap (m_cache, other.m_cache);
551 std::swap (m_cache_len, other.m_cache_len);
552}
553
554
559{
560 if (m_cache_len > 0) {
561 if (m_allcache.size() > 1) {
562 for (size_t i=0; i < m_allcache.size()-1; i++)
563 delete [] m_allcache[i];
564 m_allcache[0] = m_allcache.back();
565 m_allcache.resize(1);
566 }
567 std::fill (m_cache[0], m_cache[0] + m_cache_len, static_cast<void*>(0));
568 }
569}
570
571
580{
581 if (auxid < m_cache_len) {
582 m_cache[0][auxid] = nullptr;
583 }
584}
585
586
593{
594 // We must be holding the container lock m_mutex to call this.
595
596 if (auxid >= m_cache_len) {
597 // We need to expand the cache vector. Allocate a new one.
598 size_t newlen =
599 std::max (static_cast<SG::auxid_t>(AuxVectorData::s_minCacheLen),
600 (auxid+1)*3/2);
601 void** newcache = new void*[newlen];
602 m_allcache.push_back (newcache);
603 void** oldcache = m_cache[0];
604
605 // Copy old vector to the new one and clear the remainder.
606 std::copy (oldcache, oldcache + m_cache_len, newcache);
607 std::fill (newcache + m_cache_len, newcache + newlen,
608 static_cast<void*>(0));
609
610 // The above writes must be visible before we update the cache pointers.
612
613 // Store so that other threads can see it.
614 // The stores to m_cache must happen before the store to m_cache_len;
615 // we use a fence to ensure this.
616 m_cache[0] = newcache;
617 m_cache[1] = newcache;
619 m_cache_len = newlen;
620 }
621
622 // We have room in the cache vector now. Store the pointer.
623 m_cache[0][auxid] = ptr;
624}
625
626
634{
635 if (m_store) {
636 m_store->lock();
637 clearCache();
638 }
639
640 // No error if no store or no writable store.
641}
642
643
654{
655 bool ret = false;
656 if (m_store) {
657 // Avoid warning about calling non-const function. OK here.
659 ret = store->clearDecorations();
660 m_cache.clear();
661 m_constCache.clear();
662 m_decorCache.clear();
663 }
664 else if (getConstStore()) {
665 // The whole point of decorations is to allow adding information to
666 // something that's otherwise const. So we have the const_cast here.
667 // The store object is responsible for determining whether the
668 // modification is really allowed or not.
670 const_cast<IConstAuxStore*> (getConstStore());
671 ret = store->clearDecorations();
672 }
673 else
674 throw SG::ExcNoAuxStore ("lock");
675 return ret;
676}
677
678
688{
689 const IConstAuxStore* store = this->getConstStore();
690 if (store) {
691 // Casting away const ok if no other thread is accessing this decoration.
692 IConstAuxStore* store_nc ATLAS_THREAD_SAFE = const_cast<IConstAuxStore*> (store);
693 store_nc->lockDecoration (auxid);
694 this->clearDecorCache (auxid);
695 }
696}
697
698
708
709
710
711} // 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.
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.
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:48
Abstract interface for manipulating vectors of arbitrary types.
Interface for const operations on an auxiliary store.
virtual const SG::auxid_set_t & getDecorIDs() const =0
Return a set of identifiers for decorations in this store.
virtual void lockDecoration(SG::auxid_t auxid)=0
Lock a decoration.
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
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