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 Swap this instance with another.
297  * @param other The other instance with which to swap.
298  */
299 inline
300 void AuxVectorData::swap (AuxVectorData& other)
301 {
302  m_cache.swap (other.m_cache);
303  m_constCache.swap (other.m_constCache);
304  m_decorCache.swap (other.m_decorCache);
305  std::swap (m_store, other.m_store);
306  std::swap (m_constStore, other.m_constStore);
307  std::swap (m_constStoreLink, other.m_constStoreLink);
308 }
309 
310 
311 /**
312  * @brief Clear the cached aux data pointers.
313  *
314  * You should call this anytime something changes in the aux store
315  * that could invalidate the vector pointers.
316  */
317 inline
318 void AuxVectorData::clearCache()
319 {
320  m_cache.clear();
321  m_constCache.clear();
322  m_decorCache.clear();
323 }
324 
325 
326 /**
327  * @brief Test to see if @c auxid is valid in the cache.
328  * @returns If @c auxid is valid, return the pointer to the vector, else 0.
329  */
330 inline
331 void* AuxVectorData::Cache::cachePtr (SG::auxid_t auxid)
332 {
333  // This function is important for performance.
334  // Be careful when changing it.
335 
336  // auxid must not be larger than the length of the cache vector.
337  if (auxid >= m_cache_len) return 0;
338 #if !(defined(__x86_64__) || defined(__i386))
339  // Memory fence not strictly required on x86, and spoils optimizations.
340  // See header comments.
341  AthContainers_detail::fence_acq_rel();
342 #endif
343  // Return the cache entry.
344  return m_cache[m_cache_len&1][auxid];
345 }
346 
347 
348 /**
349  * @brief Return a pointer to the start of an aux data vector.
350  * @param auxid The desired aux data item.
351  * @param parent The containing @c AuxVectorData object.
352  *
353  * This will return a pointer to the start of the data for aux
354  * data item @c auxid. If the item doesn't exist, it will be created.
355  * Errors are signaled by raising an exception.
356  */
357 inline
358 void*
359 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
360  AuxVectorData& parent)
361 {
362  // This function is important for performance.
363  // Be careful when changing it.
364 
365  void* ptr = cachePtr (auxid);
366  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
367  // We don't have the variable cached.
368  // Call the out-of-line routine to get it cached.
369  ptr = parent.getDataOol (auxid, false);
370 
371  // These inform the compiler of what the previous call did.
372  // They tell the optimizer that it can now assume that this cache
373  // entry is valid.
374  ATHCONTAINERS_ASSUME (ptr != 0);
375  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
376  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
377  }
378  return ptr;
379 }
380 
381 
382 /**
383  * @brief Return a const pointer to the start of an aux data vector.
384  * @param auxid The desired aux data item.
385  * @param parent The containing @c AuxVectorData object.
386  *
387  * This will return a pointer to the start of the data for aux
388  * data item @c auxid.
389  * Errors are signaled by raising an exception.
390  */
391 inline
392 const void*
393 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
394  const AuxVectorData& parent)
395 {
396  // This function is important for performance.
397  // Be careful when changing it.
398 
399  const void* ptr = cachePtr (auxid);
400  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
401  // We don't have the variable cached.
402  // Call the out-of-line routine to get it cached.
403  ptr = parent.getDataOol (auxid, false);
404 
405  // These inform the compiler of what the previous call did.
406  // They tell the optimizer that it can now assume that this cache
407  // entry is valid.
408  ATHCONTAINERS_ASSUME (ptr != 0);
409  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
410  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
411  }
412  return ptr;
413 }
414 
415 
416 /**
417  * @brief Return a const pointer to the start of an aux data vector.
418  * @param auxid The desired aux data item.
419  * @param parent The containing @c AuxVectorData object.
420  *
421  * This will return a pointer to the start of the data for aux
422  * data item @c auxid. If the item does not exist,
423  * this will return nullptr rather than raising an exception.
424  */
425 inline
426 const void*
427 AuxVectorData::Cache::getDataArrayAllowMissing (SG::auxid_t auxid,
428  const AuxVectorData& parent)
429 {
430  const void* ptr = cachePtr (auxid);
431  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
432  // We don't have the variable cached.
433  // Call the out-of-line routine to get it cached.
434  ptr = parent.getDataOol (auxid, true);
435  }
436  return ptr;
437 }
438 
439 
440 /**
441  * @brief Return a pointer to the start of an aux decoration vector.
442  * @param auxid The desired aux decoration item.
443  * @param parent The containing @c AuxVectorData object.
444  *
445  * This will return a pointer to the start of the data for aux
446  * decoration item @c auxid. If the item doesn't exist, it will be created.
447  * Errors are signaled by raising an exception.
448  *
449  * The difference between @c getDecorationArray and @c getDataArray is that
450  * @c getDecorationArray takes a const container as input, but returns
451  * a non-const pointer. This will only succeed if either the
452  * container is not locked or the item was first accessed
453  * as a decoration.
454  */
455 inline
456 void* AuxVectorData::Cache::getDecorationArray (SG::auxid_t auxid,
457  const AuxVectorData& parent)
458 {
459  // This function is important for performance.
460  // Be careful when changing it.
461 
462  void* ptr = cachePtr (auxid);
463  if (ATHCONTAINERS_UNLIKELY (ptr == 0)) {
464  // We don't have the variable cached.
465  // Call the out-of-line routine to get it cached.
466  ptr = parent.getDecorationOol (auxid);
467 
468  // These inform the compiler of what the previous call did.
469  // They tell the optimizer that it can now assume that this cache
470  // entry is valid.
471  ATHCONTAINERS_ASSUME (ptr != 0);
472  ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
473  ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
474  }
475  return ptr;
476 }
477 
478 
479 /**
480  * @brief Set an option for an auxiliary data variable.
481  * @param id The variable for which we want to set the option.
482  * @param optname The name of the option to set.
483  * @param arg The option value to set.
484  *
485  * The interpretation of @c option depends on the associated auxiliary store.
486  * See PackedParameters.h for option settings for writing packed data.
487  * Returns @c true on success, @c false otherwise.
488  */
489 template <class T>
490 bool AuxVectorData::setOption (auxid_t id,
491  const std::string& optname,
492  T arg)
493 {
494  return this->setOption (id, AuxDataOption (optname, arg));
495 }
496 
497 
498 /**
499  * @brief Set an option for an auxiliary data variable.
500  * @param name The name of the variable.
501  * @param optname The name of the option to set.
502  * @param arg The option value to set.
503  *
504  * The interpretation of @c option depends on the associated auxiliary store.
505  * See PackedParameters.h for option settings for writing packed data.
506  * Returns @c true on success, @c false otherwise.
507  */
508 inline
509 bool AuxVectorData::setOption (const std::string& name,
510  const std::string& optname,
511  int arg)
512 {
513  return this->setOption (name, AuxDataOption (optname, arg));
514 }
515 inline
516 bool AuxVectorData::setOption (const std::string& name,
517  const std::string& optname,
518  float arg)
519 {
520  return this->setOption (name, AuxDataOption (optname, arg));
521 }
522 inline
523 bool AuxVectorData::setOption (const std::string& name,
524  const std::string& optname,
525  double arg)
526 {
527  return this->setOption (name, AuxDataOption (optname, arg));
528 }
529 
530 
531 /**
532  * @brief Set an option for an auxiliary data variable.
533  * @param name The name of the variable.
534  * @param clsname The name of the associated class. May be blank.
535  * @param optname The name of the option to set.
536  * @param arg The option value to set.
537  *
538  * The interpretation of @c option depends on the associated auxiliary store.
539  * See PackedParameters.h for option settings for writing packed data.
540  * Returns @c true on success, @c false otherwise.
541  */
542 template <class T>
543 bool AuxVectorData::setOption (const std::string& name,
544  const std::string& clsname,
545  const std::string& optname,
546  T arg)
547 {
548  return this->setOption (name, clsname, AuxDataOption (optname, arg));
549 }
550 
551 
552 /**
553  * @brief Explicitly set a cache pointer.
554  * @param auxid Variable ID to set.
555  * @param ptr Pointer to which the cache entry should be set.
556  *
557  * For internal use; do not use from user code.
558  * This does _not_ acquire the lock --- it's mostly meant to be used
559  * from a constructor.
560  */
561 inline
562 void AuxVectorData::setCache (SG::auxid_t auxid, void* ptr)
563 {
564  m_cache.store (auxid, ptr);
565 }
566 
567 
568 /**
569  * @brief Explicitly set a cache pointer.
570  * @param auxid Variable ID to set.
571  * @param ptr Pointer to which the cache entry should be set.
572  *
573  * For internal use; do not use from user code.
574  * This does _not_ acquire the lock --- it's mostly meant to be used
575  * from a constructor.
576  */
577 inline
578 void AuxVectorData::setCache (SG::auxid_t auxid, const void* ptr)
579 {
580  // Ok; usage of ptr is still const.
581  void* ptr_nc ATLAS_THREAD_SAFE = const_cast<void*>(ptr);
582  m_constCache.store (auxid, ptr_nc);
583 }
584 
585 
586 } // namespace SG