ATLAS Offline Software
AuxVectorData.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
19 #include <sstream>
20 
21 
22 namespace SG {
23 
24 
26 size_t AuxVectorData::s_minCacheLen = 1024;
27 
28 
31 
32 
37  : m_store(0),
38  m_constStore( 0 )
39 {
40 }
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),
53  m_constStore (rhs.m_constStore),
54  m_constStoreLink (std::move (rhs.m_constStoreLink))
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 
89 {
90 }
91 
92 
101 {
102  m_store = 0;
105  clearCache();
106 }
107 
108 
117 {
118  m_store = store;
121  clearCache();
122 }
123 
124 
133 {
134  m_store = 0;
135  m_constStore = 0;
137  clearCache();
138 }
139 
140 
151 {
152  if (id == null_auxid) return false;
154  if (!store) return false;
155  return store->setOption (id, option);
156 }
157 
158 
168 bool AuxVectorData::setOption (const std::string& name,
169  const AuxDataOption& option)
170 {
172  return setOption (id, option);
173 }
174 
175 
186 bool AuxVectorData::setOption (const std::string& name,
187  const std::string& clsname,
188  const AuxDataOption& option)
189 {
191  return setOption (id, option);
192 }
193 
194 
204 {
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 
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 
308 void* 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;
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 
455 const AuxDataSpanBase*
456 AuxVectorData::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;
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).
478  m_spanCache.store (auxid, vp);
479  }
480  else if (!allowMissing)
481  throw SG::ExcBadAuxVar (auxid);
482 
483  return ptr;
484 }
485 
486 
491  : m_cache(),
492  m_cache_len(0)
493 {
494 }
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 
705 {
706  return getConstStore();
707 }
708 
709 
710 
711 } // namespace SG
SG::AuxVectorData::getConstStore
const SG::IConstAuxStore * getConstStore() const
Return the current store, as a const interface.
SG::AuxVectorData::isAvailableOol
bool isAvailableOol(auxid_t id) const
Out-of-line portion of isAvailable.
Definition: AuxVectorData.cxx:243
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:71
SG::AuxVectorData::lock
virtual void lock() override
Lock the container.
Definition: AuxVectorData.cxx:633
SG::IConstAuxStore::lockDecoration
virtual void lockDecoration(SG::auxid_t auxid)=0
Lock a decoration.
SG::AuxVectorData::getDataOol
void * getDataOol(SG::auxid_t auxid, bool allowMissing)
Out-of-line portion of data access.
Definition: AuxVectorData.cxx:308
max
#define max(a, b)
Definition: cfImp.cxx:41
SG::AuxVectorData::m_constStoreLink
DataLink< SG::IConstAuxStore > m_constStoreLink
Associated store link, const.
Definition: AuxVectorData.h:984
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::AuxVectorData::ATLAS_THREAD_SAFE
static size_t s_minCacheLen ATLAS_THREAD_SAFE
Minimum length to use for the cache vector.
Definition: AuxVectorData.h:593
SG::AuxVectorData::clearDecorCache
void clearDecorCache(SG::auxid_t auxid)
Clear the cached decoration pointer for a single variable.
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:640
DataLinkBase::clear
void clear()
Clear the link (make it null).
Definition: DataLinkBase.cxx:36
SG::AuxVectorData::getDecorIDs
const SG::auxid_set_t & getDecorIDs() const
Return a set of identifiers for decorations for this object.
Definition: AuxVectorData.cxx:215
SG::AuxTypeRegistry::findAuxID
SG::auxid_t findAuxID(const std::string &name, const std::string &clsname="") const
Look up a name -> auxid_t mapping.
Definition: AuxTypeRegistry.cxx:757
SG::AuxVectorData::getWritableAuxIDs
const SG::auxid_set_t & getWritableAuxIDs() const
Return a set of identifiers for writable data items in this store.
Definition: AuxVectorData.cxx:231
SG::AuxVectorData::guard_t
AthContainers_detail::lock_guard< mutex_t > guard_t
Definition: AuxVectorData.h:989
SG::AuxVectorData::getDecorationOol
void * getDecorationOol(SG::auxid_t auxid) const
Out-of-line portion of data access (decorator version).
Definition: AuxVectorData.cxx:397
SG::ExcStoreLocked
Exception — Attempted to modify auxiliary data in a locked store.
Definition: Control/AthContainers/AthContainers/exceptions.h:183
SG::AuxVectorData::getDataSpanOol
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.
Definition: AuxVectorData.cxx:456
exceptions.h
Exceptions that can be thrown from AthContainers.
SG::AuxVectorData::Cache::m_cache
void ** m_cache[2]
Pointer to the cache vector.
Definition: AuxVectorData.h:855
SG::AuxVectorData::operator=
AuxVectorData & operator=(AuxVectorData &&rhs)
Move assignment.
Definition: AuxVectorData.cxx:66
SG::AuxVectorData::Cache
Manage cache of pointers to aux element vectors.
Definition: AuxVectorData.h:723
SG::AuxVectorData::getConstStoreOol
const SG::IConstAuxStore * getConstStoreOol() const
Same as getConstStore.
Definition: AuxVectorData.cxx:704
SG::AuxVectorData::Cache::Cache
Cache()
Cache manager constructor.
Definition: AuxVectorData.cxx:490
SG::AuxVectorData::lockDecoration
void lockDecoration(SG::auxid_t auxid)
Explicitly lock a decoration.
Definition: AuxVectorData.cxx:687
SG::AuxVectorData::isAvailableWritableAsDecorationOol
bool isAvailableWritableAsDecorationOol(auxid_t id) const
Out-of-line portion of isAvailableWritableAsDecoration.
Definition: AuxVectorData.cxx:282
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
SG::ExcConstAuxData
Exception — Non-const operation performed on const aux data.
Definition: Control/AthContainers/AthContainers/exceptions.h:77
SG::AuxVectorData::getDecorationArray
void * getDecorationArray(SG::auxid_t auxid) const
Return a pointer to the start of an aux data vector for a decoration.
SG::AuxVectorData::getAuxIDs
const SG::auxid_set_t & getAuxIDs() const
Return a set of identifiers for existing data items in store associated with this object.
Definition: AuxVectorData.cxx:203
AthContainers_detail::fence_seq_cst
void fence_seq_cst()
A sequentially-consistent fence.
SG::AuxVectorData::m_constStore
const SG::IConstAuxStore * m_constStore
Associated store, const.
Definition: AuxVectorData.h:980
SG::AuxVectorData::setStore
void setStore(SG::IAuxStore *store)
Set the store associated with this object.
Definition: AuxVectorData.cxx:116
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
SG::AuxVectorData::~AuxVectorData
virtual ~AuxVectorData()
Destructor.
Definition: AuxVectorData.cxx:88
SG::AuxVectorData::s_emptySet
static const SG::auxid_set_t s_emptySet
Empty auxid set, used for a return value when we have no associated store.
Definition: AuxVectorData.h:993
SG::ExcBadAuxVar
Exception — Attempt to retrieve nonexistent aux data item.
Definition: Control/AthContainers/AthContainers/exceptions.h:59
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG::AuxVectorData::m_mutex
mutex_t m_mutex
Definition: AuxVectorData.h:990
SG::AuxVectorData::Cache::operator=
Cache & operator=(Cache &&rhs)
Cache manager move assignment.
Definition: AuxVectorData.cxx:517
SG::AuxVectorData::getStore
SG::IAuxStore * getStore()
Return the current store, as a non-const interface.
error.h
Helper for emitting error messages.
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
SG::AuxVectorData::AuxVectorData
AuxVectorData()
Constructor.
Definition: AuxVectorData.cxx:36
AuxVectorData.h
Manage lookup of vectors of auxiliary data.
fill
void fill(H5::Group &out_file, size_t iterations)
Definition: test-hdf5-writer.cxx:95
SG::AuxDataOption
Hold information about an option setting request.
Definition: AuxDataOption.h:37
SG::AuxDataSpanBase
Minimal span-like object describing the range of an auxiliary variable.
Definition: AuxDataSpan.h:39
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
SG::AuxTypeRegistry::isLinked
bool isLinked(SG::auxid_t auxid) const
Test whether this is a linked variable.
SG::AuxVectorData::clearCache
void clearCache()
Clear the cached aux data pointers.
SG::AuxVectorData::Cache::clear
void clear()
Clear the cache (and free any old cache vectors).
Definition: AuxVectorData.cxx:558
SG::AuxVectorData::m_store
SG::IAuxStore * m_store
Associated store, non-const.
Definition: AuxVectorData.h:976
SG::IAuxStore::getWritableAuxIDs
virtual const SG::auxid_set_t & getWritableAuxIDs() const =0
Return a set of identifiers for writable data items in this store.
SG::IAuxStore
Interface for non-const operations on an auxiliary store.
Definition: IAuxStore.h:48
python.PyAthena.v
v
Definition: PyAthena.py:154
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
VKalVrtAthena::varHolder_detail::clear
void clear(T &var)
Definition: NtupleVars.h:48
SG::AuxVectorData::clearDecorations
bool clearDecorations() const
Clear all decorations.
Definition: AuxVectorData.cxx:653
SG::IAuxStore::getData
virtual void * getData(auxid_t auxid, size_t size, size_t capacity)=0
Return the data vector for one aux data item.
SG::AuxVectorData::Cache::swap
void swap(Cache &other)
Swap this cache object with another.
Definition: AuxVectorData.cxx:547
SG::IAuxTypeVector
Abstract interface for manipulating vectors of arbitrary types.
Definition: IAuxTypeVector.h:42
SG::IConstAuxStore::getDecorIDs
virtual const SG::auxid_set_t & getDecorIDs() const =0
Return a set of identifiers for decorations in this store.
SG::AuxVectorData::Cache::~Cache
~Cache()
Cache manager destructor.
Definition: AuxVectorData.cxx:537
SG::AuxVectorData::Cache::store
void store(SG::auxid_t auxid, void *ptr)
Store a pointer for auxid in the cache.
Definition: AuxVectorData.cxx:592
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
IAuxStore.h
Interface for non-const operations on an auxiliary store.
SG::IConstAuxStore::lock
virtual void lock()=0
Lock the container.
SG::AuxVectorData::isAvailableWritableOol
bool isAvailableWritableOol(auxid_t id)
Out-of-line portion of isAvailableWritable.
Definition: AuxVectorData.cxx:270
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
SG::AuxVectorData
Manage lookup of vectors of auxiliary data.
Definition: AuxVectorData.h:168
calibdata.copy
bool copy
Definition: calibdata.py:27
IConstAuxStore.h
Interface for const operations on an auxiliary store.
SG::IConstAuxStore
Interface for const operations on an auxiliary store.
Definition: IConstAuxStore.h:64
SG::ExcNoAuxStore
Exception — Aux data requested from object with no store.
Definition: Control/AthContainers/AthContainers/exceptions.h:34
checker_macros.h
Define macros for attributes used to control the static checker.
SG::AuxVectorData::capacity_v
virtual size_t capacity_v() const =0
Return the capacity of the container.
SG::AuxVectorData::size_v
virtual size_t size_v() const =0
Return the size of the container.
SG::AuxVectorData::setOption
bool setOption(auxid_t id, const AuxDataOption &option)
Set an option for an auxiliary data variable.
Definition: AuxVectorData.cxx:150