ATLAS Offline Software
Loading...
Searching...
No Matches
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
19namespace 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 */
28inline
29const 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 */
47inline
48const 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 */
59inline
60SG::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 */
71inline
72const 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 */
81inline
82bool 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 */
91inline
92bool 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 */
109inline
110void 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 */
120inline
121bool 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 */
133inline
134bool 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 */
146inline
147bool 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 */
167template <class T>
168inline
169typename AuxDataTraits<T>::reference_type
170AuxVectorData::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 */
188template <class T>
189inline
190typename AuxDataTraits<T>::const_reference_type
191AuxVectorData::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 */
216template <class T>
217inline
218typename AuxDataTraits<T>::reference_type
219AuxVectorData::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 */
234inline
235void*
236AuxVectorData::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 */
250inline
251const void*
252AuxVectorData::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 */
266inline
267const void*
268AuxVectorData::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 */
288inline
289void* 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 */
309inline
310const AuxDataSpanBase*
311AuxVectorData::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 */
321inline
322void 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 */
340inline
341void 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 */
358inline
359void 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 */
377inline
378void 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 */
389inline
390void* 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 */
416inline
417void*
418AuxVectorData::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 */
450inline
451const void*
452AuxVectorData::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 */
484inline
485const void*
486AuxVectorData::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 */
514inline
515void* 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 */
542inline
543const AuxDataSpanBase*
544AuxVectorData::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 */
575template <class T>
576bool 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 */
594inline
595bool AuxVectorData::setOption (const std::string& name,
596 const std::string& optname,
597 int arg)
598{
599 return this->setOption (name, AuxDataOption (optname, arg));
600}
601inline
602bool AuxVectorData::setOption (const std::string& name,
603 const std::string& optname,
604 float arg)
605{
606 return this->setOption (name, AuxDataOption (optname, arg));
607}
608inline
609bool 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 */
628template <class T>
629bool 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 */
647inline
648void 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 */
663inline
664void 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