1 // Dear emacs, this is -*- c++ -*-
3 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
6 * @file AthContainers/AuxVectorData.icc
7 * @author scott snyder <snyder@bnl.gov>
9 * @brief Manage lookup of vectors of auxiliary data.
13 #include "AthContainersInterfaces/IAuxStore.h"
14 #include "AthContainersInterfaces/IConstAuxStore.h"
15 #include "AthContainers/tools/likely.h"
16 #include "AthContainers/tools/assume.h"
23 * @brief Return the current store, as a const interface.
25 * This will be non-zero if either a const or non-const store
26 * is associated with this object.
29 const SG::IConstAuxStore* AuxVectorData::getConstStore() const
34 if( !m_constStoreLink.isDefault() ) {
35 return m_constStoreLink.cptr();
42 * @brief Return the data link to the current store, as a const interface.
44 * This is set by persistency when reading an object, but it may
45 * be overridden by setting the store pointer directly.
48 const DataLink<SG::IConstAuxStore> AuxVectorData::getConstStoreLink() const
50 return m_constStoreLink;
55 * @brief Return the current store, as a non-const interface.
57 * This will be non-zero if a non-const store is associated with this object.
60 SG::IAuxStore* AuxVectorData::getStore()
67 * @brief Return the current store, as a non-const interface.
69 * This will be non-zero if a non-const store is associated with this object.
72 const SG::IAuxStore* AuxVectorData::getStore() const
79 * @brief Return true if this object has an associated store.
82 bool AuxVectorData::hasStore() const
84 return ( getConstStore() != 0 );
89 * @brief Return true if this object has an associated non-const store.
92 bool AuxVectorData::hasNonConstStore() const
99 * @brief Set the store associated with this object.
100 * @param store The new store.
102 * This will set both the const and non-const store pointers, and also
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.
110 void AuxVectorData::setNonConstStore (SG::IAuxStore* store)
117 * @brief Test to see if a variable exists in the store.
118 * @param id The variable to test.
121 bool AuxVectorData::isAvailable (auxid_t id) const
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);
130 * @brief Test to see if a variable is available for writing.
131 * @param id The variable to test.
134 bool AuxVectorData::isAvailableWritable (auxid_t id)
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);
143 * @brief Test to see if a variable is available for writing as a decoration.
144 * @param id The variable to test.
147 bool AuxVectorData::isAvailableWritableAsDecoration (auxid_t id) const
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);
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.
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.
164 * Warning: no type checking is done. You should usually access
165 * the data via @c Accessor.
169 typename AuxDataTraits<T>::reference_type
170 AuxVectorData::getData (SG::auxid_t auxid, size_t ndx)
172 return AuxDataTraits<T>::index (this->getDataArray (auxid), ndx);
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.
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.
185 * Warning: no type checking is done. You should usually access
186 * the data via @c Accessor.
190 typename AuxDataTraits<T>::const_reference_type
191 AuxVectorData::getData (SG::auxid_t auxid, size_t ndx) const
193 return AuxDataTraits<T>::index (this->getDataArray (auxid), ndx);
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.
202 * This will return a reference to element @c ndx of aux decoration
204 * If the aux data item does not exist, it will be created.
205 * Errors are signaled by raising an exception.
207 * Warning: no type checking is done. You should usually access
208 * the data via @c Decorator.
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
218 typename AuxDataTraits<T>::reference_type
219 AuxVectorData::getDecoration (SG::auxid_t auxid, size_t ndx) const
221 return AuxDataTraits<T>::index (this->getDecorationArray (auxid), ndx);
227 * @brief Return a pointer to the start of an aux data vector.
228 * @param auxid The desired aux data item.
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.
236 AuxVectorData::getDataArray (SG::auxid_t auxid)
238 return m_cache.getDataArray (auxid, *this);
243 * @brief Return a const pointer to the start of an aux data vector.
244 * @param auxid The desired aux data item.
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.
252 AuxVectorData::getDataArray (SG::auxid_t auxid) const
254 return m_constCache.getDataArray (auxid, *this);
259 * @brief Return a const pointer to the start of an aux data vector.
260 * @param auxid The desired aux data item.
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.
268 AuxVectorData::getDataArrayAllowMissing (SG::auxid_t auxid) const
270 return m_constCache.getDataArrayAllowMissing (auxid, *this);
275 * @brief Return a pointer to the start of an aux data vector for a decoration.
276 * @param auxid The desired aux data item.
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.
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
289 void* AuxVectorData::getDecorationArray (SG::auxid_t auxid) const
291 return m_decorCache.getDecorationArray (auxid, *this);
296 * @brief Return a reference to a description of this vector's start+size.
297 * @param auxid The desired aux data item.
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.
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.
310 const AuxDataSpanBase*
311 AuxVectorData::getDataSpan (SG::auxid_t auxid) const
313 return m_spanCache.getDataSpan (auxid, *this);
318 * @brief Swap this instance with another.
319 * @param other The other instance with which to swap.
322 void AuxVectorData::swap (AuxVectorData& other)
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);
335 * @brief Clear the cached aux data pointers.
337 * You should call this anytime something changes in the aux store
338 * that could invalidate the vector pointers.
341 void AuxVectorData::clearCache()
343 guard_t guard (m_mutex);
345 m_constCache.clear();
346 m_decorCache.clear();
352 * @brief Clear the cached aux data pointers for a single variable.
353 * @param auxid ID of the variable to clear.
355 * Not really safe to use if another thread may be accessing
356 * the same decoration.
359 void AuxVectorData::clearCache (SG::auxid_t auxid)
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.
371 * @brief Clear the cached decoration pointer for a single variable.
372 * @param auxid ID of the variable to clear.
374 * Not really safe to use if another thread may be accessing
375 * the same decoration.
378 void AuxVectorData::clearDecorCache (SG::auxid_t auxid)
380 guard_t guard (m_mutex);
381 m_decorCache.clear (auxid);
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.
390 void* AuxVectorData::Cache::cachePtr (SG::auxid_t auxid)
392 // This function is important for performance.
393 // Be careful when changing it.
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();
402 // Return the cache entry.
403 return m_cache[m_cache_len&1][auxid];
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.
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.
418 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
419 AuxVectorData& parent)
421 // This function is important for performance.
422 // Be careful when changing it.
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);
430 // These inform the compiler of what the previous call did.
431 // They tell the optimizer that it can now assume that this cache
433 ATHCONTAINERS_ASSUME (ptr != 0);
434 ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
435 ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
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.
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.
452 AuxVectorData::Cache::getDataArray (SG::auxid_t auxid,
453 const AuxVectorData& parent)
455 // This function is important for performance.
456 // Be careful when changing it.
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);
464 // These inform the compiler of what the previous call did.
465 // They tell the optimizer that it can now assume that this cache
467 ATHCONTAINERS_ASSUME (ptr != 0);
468 ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
469 ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
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.
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.
486 AuxVectorData::Cache::getDataArrayAllowMissing (SG::auxid_t auxid,
487 const AuxVectorData& parent)
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);
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.
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.
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
515 void* AuxVectorData::Cache::getDecorationArray (SG::auxid_t auxid,
516 const AuxVectorData& parent)
518 // This function is important for performance.
519 // Be careful when changing it.
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);
527 // These inform the compiler of what the previous call did.
528 // They tell the optimizer that it can now assume that this cache
530 ATHCONTAINERS_ASSUME (ptr != 0);
531 ATHCONTAINERS_ASSUME (cachePtr (auxid) != 0);
532 ATHCONTAINERS_ASSUME (cachePtr (auxid) == ptr);
539 * @brief Return a reference to a description of this vector's start+size.
540 * @param auxid The desired aux data item.
543 const AuxDataSpanBase*
544 AuxVectorData::Cache::getDataSpan (SG::auxid_t auxid,
545 const AuxVectorData& parent)
547 // This function is important for performance.
548 // Be careful when changing it.
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));
556 // These inform the compiler of what the previous call did.
557 // They tell the optimizer that it can now assume that this cache
559 //ATHCONTAINERS_ASSUME (ptr != 0);
561 return reinterpret_cast<const AuxDataSpanBase*> (ptr);
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.
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.
576 bool AuxVectorData::setOption (auxid_t id,
577 const std::string& optname,
580 return this->setOption (id, AuxDataOption (optname, arg));
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.
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.
595 bool AuxVectorData::setOption (const std::string& name,
596 const std::string& optname,
599 return this->setOption (name, AuxDataOption (optname, arg));
602 bool AuxVectorData::setOption (const std::string& name,
603 const std::string& optname,
606 return this->setOption (name, AuxDataOption (optname, arg));
609 bool AuxVectorData::setOption (const std::string& name,
610 const std::string& optname,
613 return this->setOption (name, AuxDataOption (optname, arg));
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.
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.
629 bool AuxVectorData::setOption (const std::string& name,
630 const std::string& clsname,
631 const std::string& optname,
634 return this->setOption (name, clsname, AuxDataOption (optname, arg));
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.
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.
648 void AuxVectorData::setCache (SG::auxid_t auxid, void* ptr)
650 m_cache.store (auxid, ptr);
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.
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.
664 void AuxVectorData::setCache (SG::auxid_t auxid, const void* ptr)
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);