ATLAS Offline Software
AuxVectorData.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 /*
3  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 */
5 /**
6  * @file AthContainers/AuxVectorData.icc
7  * @author scott snyder <snyder@bnl.gov>
8  * @date Sep, 2013
9  * @brief Manage lookup of vectors of auxiliary data.
10  */
11 
12 
13 #include "AthContainersInterfaces/IAuxStore.h"
14 #include "AthContainersInterfaces/IConstAuxStore.h"
15 #include "AthContainers/tools/likely.h"
16 #include "AthContainers/tools/assume.h"
17 
18 
19 namespace SG {
20 
21 
22 /**
23  * @brief Return the current store, as a const interface.
24  *
25  * This will be non-zero if either a const or non-const store
26  * is associated with this object.
27  */
28 inline
29 const SG::IConstAuxStore* AuxVectorData::getConstStore() const
30 {
31  if( m_constStore ) {
32  return m_constStore;
33  }
34  if( !m_constStoreLink.isDefault() ) {
35  return m_constStoreLink.cptr();
36  }
37  return 0;
38 }
39 
40 
41 /**
42  * @brief Return the data link to the current store, as a const interface.
43  *
44  * This is set by persistency when reading an object, but it may
45  * be overridden by setting the store pointer directly.
46  */
47 inline
48 const DataLink<SG::IConstAuxStore> AuxVectorData::getConstStoreLink() const
49 {
50  return m_constStoreLink;
51 }
52 
53 
54 /**
55  * @brief Return the current store, as a non-const interface.
56  *
57  * This will be non-zero if a non-const store is associated with this object.
58  */
59 inline
60 SG::IAuxStore* AuxVectorData::getStore()
61 {
62  return m_store;
63 }
64 
65 
66 /**
67  * @brief Return the current store, as a non-const interface.
68  *
69  * This will be non-zero if a non-const store is associated with this object.
70  */
71 inline
72 const SG::IAuxStore* AuxVectorData::getStore() const
73 {
74  return m_store;
75 }
76 
77 
78 /**
79  * @brief Return true if this object has an associated store.
80  */
81 inline
82 bool AuxVectorData::hasStore() const
83 {
84  return ( getConstStore() != 0 );
85 }
86 
87 
88 /**
89  * @brief Return true if this object has an associated non-const store.
90  */
91 inline
92 bool AuxVectorData::hasNonConstStore() const
93 {
94  return m_store != 0;
95 }
96 
97 
98 /**
99  * @brief Set the store associated with this object.
100  * @param store The new store.
101  *
102  * This will set both the const and non-const store pointers, and also
103  * clear the cache.
104  * This is the same as setStore() above with the same signature.
105  * It exists so that it can be called from python; pyroot would not
106  * be able to call the non-const overload of setStore due to its
107  * simplistic overload resolution.
108  */
109 inline
110 void AuxVectorData::setNonConstStore (SG::IAuxStore* store)
111 {
112  setStore (store);
113 }
114 
115 
116 /**
117  * @brief Test to see if a variable exists in the store.
118  * @param id The variable to test.
119  */
120 inline
121 bool AuxVectorData::isAvailable (auxid_t id) const
122 {
123  // First check to see if this variable is present in the cache.
124  if (m_constCache.cachePtr (id)) return true;
125  return isAvailableOol (id);
126 }
127 
128 
129 /**
130  * @brief Test to see if a variable is available for writing.
131  * @param id The variable to test.
132  */
133 inline
134 bool AuxVectorData::isAvailableWritable (auxid_t id)
135 {
136  // First check to see if this variable is present in the cache.
137  if (m_cache.cachePtr (id)) return true;
138  return isAvailableWritableOol (id);
139 }
140 
141 
142 /**
143  * @brief Test to see if a variable is available for writing as a decoration.
144  * @param id The variable to test.
145  */
146 inline
147 bool AuxVectorData::isAvailableWritableAsDecoration (auxid_t id) const
148 {
149  // First check to see if this variable is present in the cache.
150  if (m_decorCache.cachePtr (id)) return true;
151  return isAvailableWritableAsDecorationOol (id);
152 }
153 
154 
155 /**
156  * @brief Return reference to an aux data item.
157  * @param auxid The desired aux data item.
158  * @param ndx Index of the element to return.
159  *
160  * This will return a reference to element @c ndx of aux data item @c auxid.
161  * If the aux data item does not exist, it will be created.
162  * Errors are signaled by raising an exception.
163  *
164  * Warning: no type checking is done. You should usually access
165  * the data via @c Accessor.
166  */
167 template <class T>
168 inline
169 typename AuxDataTraits<T>::reference_type
170 AuxVectorData::getData (SG::auxid_t auxid, size_t ndx)
171 {
172  return AuxDataTraits<T>::index (this->getDataArray (auxid), ndx);
173 }
174 
175 
176 /**
177  * @brief Return const reference to an aux data item.
178  * @param auxid The desired aux data item.
179  * @param ndx Index of the element to return.
180  *
181  * This will return a reference to element @c ndx of aux data item @c auxid.
182  * If the aux data item does not exist, it will be created.
183  * Errors are signaled by raising an exception.
184  *
185  * Warning: no type checking is done. You should usually access
186  * the data via @c Accessor.
187  */
188 template <class T>
189 inline
190 typename AuxDataTraits<T>::const_reference_type
191 AuxVectorData::getData (SG::auxid_t auxid, size_t ndx) const
192 {
193  return AuxDataTraits<T>::index (this->getDataArray (auxid), ndx);
194 }
195 
196 
197 /**
198  * @brief Return reference to an aux decoration item.
199  * @param auxid The desired aux decoration item.
200  * @param ndx Index of the element to return.
201  *
202  * This will return a reference to element @c ndx of aux decoration
203  * item @c auxid.
204  * If the aux data item does not exist, it will be created.
205  * Errors are signaled by raising an exception.
206  *
207  * Warning: no type checking is done. You should usually access
208  * the data via @c Decorator.
209  *
210  * The difference between @c getDecoration and @c getData is that
211  * @c getDecoration takes a const container as input, but returns
212  * a non-const reference. This will only succeed if either the
213  * container is not locked or the item was first accessed
214  * as a decoration.
215  */
216 template <class T>
217 inline
218 typename AuxDataTraits<T>::reference_type
219 AuxVectorData::getDecoration (SG::auxid_t auxid, size_t ndx) const
220 {
221  return AuxDataTraits<T>::index (this->getDecorationArray (auxid), ndx);
222 }
223 
224 
225 
226 /**
227  * @brief Return a pointer to the start of an aux data vector.
228  * @param auxid The desired aux data item.
229  *
230  * This will return a pointer to the start of the data for aux
231  * data item @c auxid. If the item doesn't exist, it will be created.
232  * Errors are signaled by raising an exception.
233  */
234 inline
235 void*
236 AuxVectorData::getDataArray (SG::auxid_t auxid)
237 {
238  return m_cache.getDataArray (auxid, *this);
239 }
240 
241 
242 /**
243  * @brief Return a const pointer to the start of an aux data vector.
244  * @param auxid The desired aux data item.
245  *
246  * This will return a pointer to the start of the data for aux
247  * data item @c auxid.
248  * Errors are signaled by raising an exception.
249  */
250 inline
251 const void*
252 AuxVectorData::getDataArray (SG::auxid_t auxid) const
253 {
254  return m_constCache.getDataArray (auxid, *this);
255 }
256 
257 
258 /**
259  * @brief Return a const pointer to the start of an aux data vector.
260  * @param auxid The desired aux data item.
261  *
262  * This will return a pointer to the start of the data for aux
263  * data item @c auxid. If the item does not exist,
264  * this will return nullptr rather than raising an exception.
265  */
266 inline
267 const void*
268 AuxVectorData::getDataArrayAllowMissing (SG::auxid_t auxid) const
269 {
270  return m_constCache.getDataArrayAllowMissing (auxid, *this);
271 }
272 
273 
274 /**
275  * @brief Return a pointer to the start of an aux data vector for a decoration.
276  * @param auxid The desired aux data item.
277  *
278  * This will return a pointer to the start of the data for aux
279  * data item @c auxid. If the item doesn't exist, it will be created.
280  * Errors are signaled by raising an exception.
281  *
282  * The difference between @c getDecorationArray and @c getDataArray is that
283  * @c getDecorationArray takes a const container as input, but returns
284  * a non-const pointer. This will only succeed if either the
285  * container is not locked or the item was first accessed
286  * as a decoration.
287  */
288 inline
289 void* AuxVectorData::getDecorationArray (SG::auxid_t auxid) const
290 {
291  return m_decorCache.getDecorationArray (auxid, *this);
292 }
293 
294 
295 /**
296  * @brief Return a reference to a description of this vector's start+size.
297  * @param auxid The desired aux data item.
298  *
299  * This low-overhead method of getting the start+size of an auxiliary
300  * variable. The returned object will be updated if the variable's
301  * vector changes. Raises an exception if the variable does not exist.
302  *
303  * This is in principle a const-correctness violation,
304  * since @c AuxDataSpanBase has a non-const pointer to the start
305  * of the vector. But doing it properly is kind of painful, and as
306  * this interface is only meant to be used internally, it's likely
307  * not a real problem.
308  */
309 inline
310 const AuxDataSpanBase*
311 AuxVectorData::getDataSpan (SG::auxid_t auxid) const
312 {
313  return m_spanCache.getDataSpan (auxid, *this);
314 }
315 
316 
317 /**
318  * @brief Swap this instance with another.
319  * @param other The other instance with which to swap.
320  */
321 inline
322 void AuxVectorData::swap (AuxVectorData& other)
323 {
324  m_cache.swap (other.m_cache);
325  m_constCache.swap (other.m_constCache);
326  m_decorCache.swap (other.m_decorCache);
327  m_spanCache.swap (other.m_spanCache);
328  std::swap (m_store, other.m_store);
329  std::swap (m_constStore, other.m_constStore);
330  std::swap (m_constStoreLink, other.m_constStoreLink);
331 }
332 
333 
334 /**
335  * @brief Clear the cached aux data pointers.
336  *
337  * You should call this anytime something changes in the aux store
338  * that could invalidate the vector pointers.
339  */
340 inline
341 void AuxVectorData::clearCache()
342 {
343  guard_t guard (m_mutex);
344  m_cache.clear();
345  m_constCache.clear();
346  m_decorCache.clear();
347  m_spanCache.clear();
348 }
349 
350 
351 /**
352  * @brief Clear the cached aux data pointers for a single variable.
353  * @param auxid ID of the variable to clear.
354  *
355  * Not really safe to use if another thread may be accessing
356  * the same decoration.
357  */
358 inline
359 void AuxVectorData::clearCache (SG::auxid_t auxid)
360 {
361  guard_t guard (m_mutex);
362  m_cache.clear (auxid);
363  m_constCache.clear (auxid);
364  m_decorCache.clear (auxid);
365  // Don't clear the span cache here --- the referenced spans get updated
366  // automatically as needed.
367 }
368 
369 
370 /**
371  * @brief Clear the cached decoration pointer for a single variable.
372  * @param auxid ID of the variable to clear.
373  *
374  * Not really safe to use if another thread may be accessing
375  * the same decoration.
376  */
377 inline
378 void AuxVectorData::clearDecorCache (SG::auxid_t auxid)
379 {
380  guard_t guard (m_mutex);
381  m_decorCache.clear (auxid);
382 }
383 
384 
385 /**
386  * @brief Test to see if @c auxid is valid in the cache.
387  * @returns If @c auxid is valid, return the pointer to the vector, else 0.
388  */
389 inline
390 void* AuxVectorData::Cache::cachePtr (SG::auxid_t auxid)
391 {
392  // This function is important for performance.
393  // Be careful when changing it.
394 
395  // auxid must not be larger than the length of the cache vector.
396  if (auxid >= m_cache_len) return 0;
397 #if !(defined(__x86_64__) || defined(__i386))
398  // Memory fence not strictly required on x86, and spoils optimizations.
399  // See header comments.
400  AthContainers_detail::fence_acq_rel();
401 #endif
402  // Return the cache entry.
403  return m_cache[m_cache_len&1][auxid];
404 }
405 
406 
407 /**
408  * @brief Return a pointer to the start of an aux data vector.
409  * @param auxid The desired aux data item.
410  * @param parent The containing @c AuxVectorData object.
411  *
412  * This will return a pointer to the start of the data for aux
413  * data item @c auxid. If the item doesn't exist, it will be created.
414  * Errors are signaled by raising an exception.
415  */
416 inline
417 void*
418 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
419  AuxVectorData& parent)
420 {
421  // This function is important for performance.
422  // Be careful when changing it.
423 
424  void* ptr = cachePtr (auxid);
425  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
426  // We don't have the variable cached.
427  // Call the out-of-line routine to get it cached.
428  ptr = parent.getDataOol (auxid, false);
429 
430  // These inform the compiler of what the previous call did.
431  // They tell the optimizer that it can now assume that this cache
432  // entry is valid.
433  ATHCONTAINERS_ASSUME (ptr != 0);
434  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
435  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
436  }
437  return ptr;
438 }
439 
440 
441 /**
442  * @brief Return a const pointer to the start of an aux data vector.
443  * @param auxid The desired aux data item.
444  * @param parent The containing @c AuxVectorData object.
445  *
446  * This will return a pointer to the start of the data for aux
447  * data item @c auxid.
448  * Errors are signaled by raising an exception.
449  */
450 inline
451 const void*
452 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
453  const AuxVectorData& parent)
454 {
455  // This function is important for performance.
456  // Be careful when changing it.
457 
458  const void* ptr = cachePtr (auxid);
459  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
460  // We don't have the variable cached.
461  // Call the out-of-line routine to get it cached.
462  ptr = parent.getDataOol (auxid, false);
463 
464  // These inform the compiler of what the previous call did.
465  // They tell the optimizer that it can now assume that this cache
466  // entry is valid.
467  ATHCONTAINERS_ASSUME (ptr != 0);
468  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
469  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
470  }
471  return ptr;
472 }
473 
474 
475 /**
476  * @brief Return a const pointer to the start of an aux data vector.
477  * @param auxid The desired aux data item.
478  * @param parent The containing @c AuxVectorData object.
479  *
480  * This will return a pointer to the start of the data for aux
481  * data item @c auxid. If the item does not exist,
482  * this will return nullptr rather than raising an exception.
483  */
484 inline
485 const void*
486 AuxVectorData::Cache::getDataArrayAllowMissing (SG::auxid_t auxid,
487  const AuxVectorData& parent)
488 {
489  const void* ptr = cachePtr (auxid);
490  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
491  // We don't have the variable cached.
492  // Call the out-of-line routine to get it cached.
493  ptr = parent.getDataOol (auxid, true);
494  }
495  return ptr;
496 }
497 
498 
499 /**
500  * @brief Return a pointer to the start of an aux decoration vector.
501  * @param auxid The desired aux decoration item.
502  * @param parent The containing @c AuxVectorData object.
503  *
504  * This will return a pointer to the start of the data for aux
505  * decoration item @c auxid. If the item doesn't exist, it will be created.
506  * Errors are signaled by raising an exception.
507  *
508  * The difference between @c getDecorationArray and @c getDataArray is that
509  * @c getDecorationArray takes a const container as input, but returns
510  * a non-const pointer. This will only succeed if either the
511  * container is not locked or the item was first accessed
512  * as a decoration.
513  */
514 inline
515 void* AuxVectorData::Cache::getDecorationArray (SG::auxid_t auxid,
516  const AuxVectorData& parent)
517 {
518  // This function is important for performance.
519  // Be careful when changing it.
520 
521  void* ptr = cachePtr (auxid);
522  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
523  // We don't have the variable cached.
524  // Call the out-of-line routine to get it cached.
525  ptr = parent.getDecorationOol (auxid);
526 
527  // These inform the compiler of what the previous call did.
528  // They tell the optimizer that it can now assume that this cache
529  // entry is valid.
530  ATHCONTAINERS_ASSUME (ptr != 0);
531  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
532  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
533  }
534  return ptr;
535 }
536 
537 
538 /**
539  * @brief Return a reference to a description of this vector's start+size.
540  * @param auxid The desired aux data item.
541  */
542 inline
543 const AuxDataSpanBase*
544 AuxVectorData::Cache::getDataSpan (SG::auxid_t auxid,
545  const AuxVectorData& parent)
546 {
547  // This function is important for performance.
548  // Be careful when changing it.
549 
550  const void* ptr = cachePtr (auxid);
551  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
552  // We don't have the variable cached.
553  // Call the out-of-line routine to get it cached.
554  ptr = static_cast<const void*>(parent.getDataSpanOol (auxid, false));
555 
556  // These inform the compiler of what the previous call did.
557  // They tell the optimizer that it can now assume that this cache
558  // entry is valid.
559  //ATHCONTAINERS_ASSUME (ptr != 0);
560  }
561  return reinterpret_cast<const AuxDataSpanBase*> (ptr);
562 }
563 
564 
565 /**
566  * @brief Set an option for an auxiliary data variable.
567  * @param id The variable for which we want to set the option.
568  * @param optname The name of the option to set.
569  * @param arg The option value to set.
570  *
571  * The interpretation of @c option depends on the associated auxiliary store.
572  * See PackedParameters.h for option settings for writing packed data.
573  * Returns @c true on success, @c false otherwise.
574  */
575 template <class T>
576 bool AuxVectorData::setOption (auxid_t id,
577  const std::string& optname,
578  T arg)
579 {
580  return this->setOption (id, AuxDataOption (optname, arg));
581 }
582 
583 
584 /**
585  * @brief Set an option for an auxiliary data variable.
586  * @param name The name of the variable.
587  * @param optname The name of the option to set.
588  * @param arg The option value to set.
589  *
590  * The interpretation of @c option depends on the associated auxiliary store.
591  * See PackedParameters.h for option settings for writing packed data.
592  * Returns @c true on success, @c false otherwise.
593  */
594 inline
595 bool AuxVectorData::setOption (const std::string& name,
596  const std::string& optname,
597  int arg)
598 {
599  return this->setOption (name, AuxDataOption (optname, arg));
600 }
601 inline
602 bool AuxVectorData::setOption (const std::string& name,
603  const std::string& optname,
604  float arg)
605 {
606  return this->setOption (name, AuxDataOption (optname, arg));
607 }
608 inline
609 bool AuxVectorData::setOption (const std::string& name,
610  const std::string& optname,
611  double arg)
612 {
613  return this->setOption (name, AuxDataOption (optname, arg));
614 }
615 
616 
617 /**
618  * @brief Set an option for an auxiliary data variable.
619  * @param name The name of the variable.
620  * @param clsname The name of the associated class. May be blank.
621  * @param optname The name of the option to set.
622  * @param arg The option value to set.
623  *
624  * The interpretation of @c option depends on the associated auxiliary store.
625  * See PackedParameters.h for option settings for writing packed data.
626  * Returns @c true on success, @c false otherwise.
627  */
628 template <class T>
629 bool AuxVectorData::setOption (const std::string& name,
630  const std::string& clsname,
631  const std::string& optname,
632  T arg)
633 {
634  return this->setOption (name, clsname, AuxDataOption (optname, arg));
635 }
636 
637 
638 /**
639  * @brief Explicitly set a cache pointer.
640  * @param auxid Variable ID to set.
641  * @param ptr Pointer to which the cache entry should be set.
642  *
643  * For internal use; do not use from user code.
644  * This does _not_ acquire the lock --- it's mostly meant to be used
645  * from a constructor.
646  */
647 inline
648 void AuxVectorData::setCache (SG::auxid_t auxid, void* ptr)
649 {
650  m_cache.store (auxid, ptr);
651 }
652 
653 
654 /**
655  * @brief Explicitly set a cache pointer.
656  * @param auxid Variable ID to set.
657  * @param ptr Pointer to which the cache entry should be set.
658  *
659  * For internal use; do not use from user code.
660  * This does _not_ acquire the lock --- it's mostly meant to be used
661  * from a constructor.
662  */
663 inline
664 void AuxVectorData::setCache (SG::auxid_t auxid, const void* ptr)
665 {
666  // Ok; usage of ptr is still const.
667  void* ptr_nc ATLAS_THREAD_SAFE = const_cast<void*>(ptr);
668  m_constCache.store (auxid, ptr_nc);
669 }
670 
671 
672 } // namespace SG