2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
6 * @file AthContainers/AuxVectorBase.icc
7 * @author scott snyder <snyder@bnl.gov>
9 * @brief Manage index tracking and synchronization of auxiliary data.
17 * @brief Return true if index tracking is enabled for this container.
20bool AuxVectorBase::trackIndices() const
22 return m_trackIndices;
27 * @brief Synonym for @c setStore with @c IConstAuxStore.
28 * @param store The new store.
31void AuxVectorBase::setConstStore (const SG::IConstAuxStore* store)
38 * @brief Synonym for @c setStore with @c IAuxStore.
39 * @param store The new store.
42void AuxVectorBase::setNonConstStore (SG::IAuxStore* store)
49 * @brief Test to see if a variable exists in the store.
50 * @param name Name of the aux variable.
51 * @param clsname The name of the associated class. May be blank.
55bool AuxVectorBase::isAvailable (const std::string& name,
56 const std::string& clsname /*= ""*/) const
58 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name, clsname);
59 return AuxVectorData::isAvailable (id);
64 * @brief Test to see if a variable is available for writing.
65 * @param name Name of the aux variable.
66 * @param clsname The name of the associated class. May be blank.
71AuxVectorBase::isAvailableWritable (const std::string& name,
72 const std::string& clsname /*= ""*/)
74 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name, clsname);
75 return AuxVectorData::isAvailableWritable (id);
80 * @brief Test to see if a variable is available for writing as a decoration.
81 * @param name Name of the aux variable.
82 * @param clsname The name of the associated class. May be blank.
87AuxVectorBase::isAvailableWritableAsDecoration (const std::string& name,
88 const std::string& clsname /*= ""*/) const
90 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name, clsname);
91 return AuxVectorData::isAvailableWritableAsDecoration (id);
96 * @brief Return a span over an aux data item.
97 * @param auxid The desired aux data item.
99 * This will return a span containing the value of the requested
100 * auxiliary variable for all elements in the container.
101 * If the item doesn't exist, it will be created.
102 * Errors are signaled by raising an exception.
103 * Note that the @c value_type of the span is not necessarily @c T;
104 * an example is @c bool for which we return a span of @c char.
107AuxVectorBase::span<T> AuxVectorBase::getDataSpan (const std::string& name)
109 using container_pointer_type = typename AuxDataTraits<T>::container_pointer_type;
110 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name);
111 auto beg = reinterpret_cast<container_pointer_type> (AuxVectorData::getDataArray (id));
112 return span<T> (beg, size_v());
117 * @brief Return a span over an aux data item.
118 * @param auxid The desired aux data item.
120 * This will return a span containing the value of the requested
121 * auxiliary variable for all elements in the container.
122 * If the item doesn't exist, it will be created.
123 * Errors are signaled by raising an exception.
124 * Note that the @c value_type of the span is not necessarily @c T;
125 * an example is @c bool for which we return a span of @c char.
128AuxVectorBase::const_span<T>
129AuxVectorBase::getDataSpan (const std::string& name) const
131 using const_container_pointer_type = typename AuxDataTraits<T>::const_container_pointer_type;
132 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name);
133 auto beg = reinterpret_cast<const_container_pointer_type> (AuxVectorData::getDataArray (id));
134 return const_span<T> (beg, size_v());
139 * @brief Return a span over an aux data item for a decoration.
140 * @param auxid The desired aux data item.
142 * This will return a span containing the value of the requested
143 * auxiliary variable for all elements in the container.
144 * If the item doesn't exist, it will be created.
145 * Errors are signaled by raising an exception.
146 * Note that the @c value_type of the span is not necessarily @c T;
147 * an example is @c bool for which we return a span of @c char.
149 * The difference between @c getDecorationSpan and @c getDataSpan is that
150 * @c getDecorationSpan takes a const container as input, but returns
151 * a span over non-const objects. This will only succeed if either the
152 * container is not locked or the item was first accessed
156AuxVectorBase::span<T>
157AuxVectorBase::getDecorationSpan (const std::string& name) const
159 using container_pointer_type = typename AuxDataTraits<T>::container_pointer_type;
160 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name);
161 auto beg = reinterpret_cast<container_pointer_type> (AuxVectorData::getDecorationArray (id));
162 return span<T> (beg, size_v());
167 * @brief Return a span over an aux data item.
168 * @param auxid The desired aux data item.
170 * This will return a span containing the value of the requested
171 * auxiliary variable for all elements in the container.
172 * If the item doesn't exist, it will be created.
173 * Errors are signaled by raising an exception.
174 * Note that the @c value_type of the span is not necessarily @c T;
175 * an example is @c bool for which we return a span of @c char.
178AuxVectorBase::const_span<T>
179AuxVectorBase::getConstDataSpan (const std::string& name) const
181 using const_container_pointer_type = typename AuxDataTraits<T>::const_container_pointer_type;
182 auxid_t id = SG::AuxTypeRegistry::instance().getAuxID<T> (name);
183 auto beg = reinterpret_cast<const_container_pointer_type> (AuxVectorData::getDataArray (id));
184 return const_span<T> (beg, size_v());
189 * @brief Initialize index tracking mode.
190 * @param ownPolicy The container ownership policy.
191 * @param indexTrackingPolicy The requested index tracking policy.
193 * DVL should be the most-derived class for this container.
195 * This handles the logic for setting the state of index tracking.
196 * If this container does not handle aux data, then index tracking
197 * is always off. Otherwise, it depends on the requested policies.
198 * In any case, it is an error to turn off index tracking
199 * for a container that has an associated aux store.
204AuxVectorBase::initAuxVectorBase (SG::OwnershipPolicy ownPolicy,
205 SG::IndexTrackingPolicy indexTrackingPolicy)
207 // Forward to the appropriate specialization, depending on whether
208 // or not aux data is supported.
209 this->initAuxVectorBase1 (typename AuxStore_traits<DVL>::flag(),
211 indexTrackingPolicy);
216 * @brief Swap with another container.
217 * @param other The container with which to swap.
220void AuxVectorBase::swap (AuxVectorBase& other)
222 std::swap (m_trackIndices, other.m_trackIndices);
223 SG::AuxVectorData::swap (other);
228 * @brief Set container/index for all elements within a range.
229 * @param beg Beginning of the range.
230 * @param end End of the range.
231 * @param first Index to set for the first element in the range.
233 * For all elements in the range, the container will be set to this container,
234 * and indices will be set sequentially, starting with @c first.
236 * @c ForwardIterator should be an iterator over the @c DataVector
237 * (not a base iterator).
239template <class ForwardIterator>
241void AuxVectorBase::setIndices (ForwardIterator beg,
243 size_t first /*= 0*/)
245 // Forward to the appropriate specialization, depending on whether
246 // or not aux data is supported.
247 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
248 setIndices1 (typename AuxStore_traits<valtype>::flag(),
254 * @brief Set container/index for all elements within a range.
255 * @param beg Beginning of the range.
256 * @param end End of the range.
257 * @param first Index to set for the first element in the range.
259 * This is the no-auxdata case; doesn't do anything other than checking
262template <class ForwardIterator>
264void AuxVectorBase::setIndices1 (const std::false_type&,
269 ATHCONTAINERS_ASSERT (!m_trackIndices);
274 * @brief Set container/index for all elements within a range.
275 * @param beg Beginning of the range.
276 * @param end End of the range.
277 * @param first Index to set for the first element in the range.
279 * This is the auxdata case.
280 * For all elements in the range, the container will be set to this container,
281 * and indices will be set sequentially, starting with @c first.
283template <class ForwardIterator>
284void AuxVectorBase::setIndices1 (const std::true_type&,
292 for (; beg != end; ++beg) {
294 (*beg)->setIndex (first, this);
301 * @brief Clear the container / index for element @c elt.
302 * @param elt Iterator to the element to clear.
304 * @c ForwardIterator should be an iterator over the @c DataVector
305 * (not a base iterator).
307template <class ForwardIterator>
309void AuxVectorBase::clearIndex (ForwardIterator elt)
311 // Forward to the appropriate specialization, depending on whether
312 // or not aux data is supported.
313 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
314 clearIndex1 (typename AuxStore_traits<valtype>::flag(), elt);
319 * @brief Clear the container / index for element @c elt.
320 * @param elt Iterator to the element to clear.
322 * This is the no-auxdata case; doesn't do anything other than checking
325template <class ForwardIterator>
327void AuxVectorBase::clearIndex1 (const std::false_type&,
328 ForwardIterator /*elt*/)
330 ATHCONTAINERS_ASSERT (!m_trackIndices);
335 * @brief Clear the container / index for element @c elt.
336 * @param elt Iterator to the element to clear.
338 * This is the auxdata case.
340template <class ForwardIterator>
341void AuxVectorBase::clearIndex1 (const std::true_type&,
348 (*elt)->setIndex (0, 0);
353 * @brief Clear the container / index for a range of elements.
354 * @param beg Beginning of the range.
355 * @param end End of the range.
357 * @c ForwardIterator should be an iterator over the @c DataVector
358 * (not a base iterator).
360template <class ForwardIterator>
361void AuxVectorBase::clearIndices (ForwardIterator beg,
364 // Forward to the appropriate specialization, depending on whether
365 // or not aux data is supported.
366 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
367 clearIndices1 (typename AuxStore_traits<valtype>::flag(),
373 * @brief Clear the container / index for a range of elements.
374 * @param beg Beginning of the range.
375 * @param end End of the range.
377 * No-auxdata case; a no-op except for checking @c m_trackIndices.
379template <class ForwardIterator>
381void AuxVectorBase::clearIndices1 (const std::false_type&,
385 ATHCONTAINERS_ASSERT (!m_trackIndices);
390 * @brief Clear the container / index for a range of elements.
391 * @param beg Beginning of the range.
392 * @param end End of the range.
396template <class ForwardIterator>
397void AuxVectorBase::clearIndices1 (const std::true_type&,
404 for (; beg != end; ++beg)
406 (*beg)->setIndex (0, 0);
411 * @brief Resize the aux data associated with this container.
412 * @param size The new container size.
414 * DVL should be the most-derived class for this container.
418void AuxVectorBase::resize (size_t size)
420 // Forward to the appropriate specialization, depending on whether
421 // or not aux data is supported.
422 resize1 (typename AuxStore_traits<DVL>::flag(), size);
427 * @brief Resize the aux data associated with this container.
428 * @param size The new container size.
430 * The no-auxdata case; a no-op except for checking @c m_trackIndices.
434AuxVectorBase::resize1 (const std::false_type&, size_t /*size*/)
436 ATHCONTAINERS_ASSERT (!m_trackIndices);
441 * @brief Change the capacity of the aux data associated with this container.
442 * @param size The new container size.
444 * DVL should be the most-derived class for this container.
448void AuxVectorBase::reserve (size_t size)
450 // Forward to the appropriate specialization, depending on whether
451 // or not aux data is supported.
452 reserve1 (typename AuxStore_traits<DVL>::flag(), size);
457 * @brief Change the capacity of the aux data associated with this container.
458 * @param size The new container size.
460 * The no-auxdata case; a no-op except for checking @c m_trackIndices.
463void AuxVectorBase::reserve1 (const std::false_type&, size_t)
465 ATHCONTAINERS_ASSERT (!m_trackIndices);
470 * @brief Shift the elements of the container.
471 * @param cont The container that's being shifted.
472 * @param pos The starting index for the shift.
473 * @param offs The (signed) amount of the shift.
475 * The container should be the derived container.
476 * The elements in the container should have already been shifted;
477 * this operation will then adjust the element indices and also shift
478 * the elements in the vectors for all aux data items.
479 * @c offs may be either positive or negative.
481 * If @c offs is positive, then the container is growing.
482 * The container size should be increased by @c offs,
483 * the element at @c pos moved to @c pos + @c offs,
484 * and similarly for following elements.
485 * The elements between @c pos and @c pos + @c offs should
486 * be default-initialized.
488 * If @c offs is negative, then the container is shrinking.
489 * The element at @c pos should be moved to @c pos + @c offs,
490 * and similarly for following elements.
491 * The container should then be shrunk by @c -offs elements
492 * (running destructors as appropriate).
496void AuxVectorBase::shift (DVL& cont,
500 // Forward to the appropriate specialization, depending on whether
501 // or not aux data is supported.
502 shift1 (typename AuxStore_traits<DVL>::flag(),
508 * @brief Shift the elements of the container.
509 * @param cont The container that's being shifted.
510 * @param pos The starting index for the shift.
511 * @param offs The (signed) amount of the shift.
513 * No-auxdata version; a no-op except for checking @c m_trackIndices.
517void AuxVectorBase::shift1 (const std::false_type&,
519 size_t /*pos*/, ptrdiff_t /*offs*/)
521 ATHCONTAINERS_ASSERT (!m_trackIndices);
526 * @brief Shift the elements of the container.
527 * @param cont The container that's being shifted.
528 * @param pos The starting index for the shift.
529 * @param offs The (signed) amount of the shift.
533 * The container should be the derived container.
534 * The elements in the container should have already been shifted;
535 * this operation will then adjust the element indices and also shift
536 * the elements in the vectors for all aux data items.
537 * @c offs may be either positive or negative.
539 * If @c offs is positive, then the container is growing.
540 * The container size should be increased by @c offs,
541 * the element at @c pos moved to @c pos + @c offs,
542 * and similarly for following elements.
543 * The elements between @c pos and @c pos + @c offs should
544 * be default-initialized.
546 * If @c offs is negative, then the container is shrinking.
547 * The element at @c pos should be moved to @c pos + @c offs,
548 * and similarly for following elements.
549 * The container should then be shrunk by @c -offs elements
550 * (running destructors as appropriate).
553void AuxVectorBase::shift1 (const std::true_type&,
555 size_t pos, ptrdiff_t offs)
557 if (!m_trackIndices) return;
559 typename DVL::iterator end = cont.end();
560 typename DVL::iterator pos_it = cont.begin() + pos + offs;
561 for (; pos_it != end; ++pos_it)
563 SG::AuxElement* elt = *pos_it;
564 elt->setIndex (elt->index() + offs, this);
567 if (this->hasNonConstStore()) {
568 this->getStore()->shift (pos, offs);
571 else if (this->hasStore())
572 throw SG::ExcConstAuxData ("shift");
577 * @brief Set index on an element and copy auxiliary data.
578 * @param index Container index at which the new element is being added.
579 * @param p The new element being added.
580 * @param clear If true, then any auxiliary data initially associated
581 * with @c p are cleared after being copied.
582 * @param skipDestClear Normally, if the elements do not have auxiliary data,
583 * then the variables of the destination are cleared.
584 * If this flag is true, then this clear is skipped.
585 * This can be appropriate as part of a push_back,
586 * where the destination is already known to be clear.
588 * Overload for the no-auxdata case.
592AuxVectorBase::moveAux (size_t /*index*/,
594 bool /*clear = false*/,
595 bool /*skipDestClear = false*/)
597 ATHCONTAINERS_ASSERT (!m_trackIndices);
602 * @brief Set index on a range of elements and copy auxiliary data.
603 * @param index Container index at which the first new element is being added.
604 * @param beg The start of the range of new elements.
605 * @param end The end of the range of new elements.
606 * @param clear If true, then any auxiliary data initially associated
607 * with the elements are cleared after being copied.
608 * @param skipDestClear Normally, if the elements do not have auxiliary data,
609 * then the variables of the destination are cleared.
610 * If this flag is true, then this clear is skipped.
611 * This can be appropriate as part of a push_back,
612 * where the destination is already known to be clear.
614 * The elements in the range are being a added to the container at @c index.
615 * If the new elements have associated auxiliary data,
616 * copy it to the container starting at @c index.
617 * Then set the container / index on the elements in the range.
619 * @c ForwardIterator should be an iterator over the @c DataVector
620 * (not a base iterator).
622template <class ForwardIterator>
624AuxVectorBase::moveAux (size_t index, ForwardIterator beg, ForwardIterator end,
625 bool clear /*= false*/,
626 bool skipDestClear /*= false*/)
628 // Forward to the appropriate specialization, depending on whether
629 // or not aux data is supported.
630 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
631 moveAux1 (typename AuxStore_traits<valtype>::flag(),
632 index, beg, end, clear, skipDestClear);
637 * @brief Set index on a range of elements and copy auxiliary data.
638 * @param index Container index at which the first new element is being added.
639 * @param beg The start of the range of new elements.
640 * @param end The end of the range of new elements.
641 * @param clear If true, then any auxiliary data initially associated
642 * with the elements are cleared after being copied.
643 * @param skipDestClear Normally, if the elements do not have auxiliary data,
644 * then the variables of the destination are cleared.
645 * If this flag is true, then this clear is skipped.
646 * This can be appropriate as part of a push_back,
647 * where the destination is already known to be clear.
649 * No-auxdata version; a no-op except for checking @c m_trackIndices.
651template <class ForwardIterator>
653void AuxVectorBase::moveAux1 (const std::false_type&,
655 ForwardIterator /*beg*/,
656 ForwardIterator /*end*/,
657 bool /*clear = false*/,
658 bool /*skipDestClear = false*/)
660 ATHCONTAINERS_ASSERT (!m_trackIndices);
665 * @brief Set index on a range of elements and copy auxiliary data.
666 * @param index Container index at which the first new element is being added.
667 * @param beg The start of the range of new elements.
668 * @param end The end of the range of new elements.
669 * @param clear If true, then any auxiliary data initially associated
670 * with the elements are cleared after being copied.
671 * @param skipDestClear Normally, if the elements do not have auxiliary data,
672 * then the variables of the destination are cleared.
673 * If this flag is true, then this clear is skipped.
674 * This can be appropriate as part of a push_back,
675 * where the destination is already known to be clear.
677 * The elements in the range are being a added to the container at @c index.
678 * If the new elements have associated auxiliary data,
679 * copy it to the container starting at @c index.
680 * Then set the container / index on the elements in the range.
684template <class ForwardIterator>
685void AuxVectorBase::moveAux1 (const std::true_type&,
689 bool clear /*= false*/,
690 bool skipDestClear /*= false*/)
696 this->moveAux (index, *beg, clear, skipDestClear);
704 * @brief Set index on an element and copy auxiliary data,
705 * specialized for the case of no clearing (and inlined).
706 * @param index Container index at which the new element is being added.
707 * @param p The new element being added.
709 * Element @c p is being added to the container at @c index.
710 * If @c p has associated auxiliary data, copy it to the container
711 * at @c index. Then set the container / index on @c p.
713 * This is equivalent to moveAux with clear=false and skipDestClear=true.
714 * m_trackIndices must also be true to call this.
717void AuxVectorBase::moveAuxNoClear (size_t index, SG::AuxElement* p)
720 AuxElement::copyAuxHelper (*this, index, *p, false);
722 p->setIndex (index, this);
727 * @brief Set index on an element and copy auxiliary data,
728 * specialized for the case of no clearing (and inlined).
729 * @param index Container index at which the new element is being added.
730 * @param p The new element being added.
732 * Element @c p is being added to the container at @c index.
733 * If @c p has associated auxiliary data, copy it to the container
734 * at @c index. Then set the container / index on @c p.
736 * This is equivalent to moveAux with clear=false and skipDestClear=true.
737 * m_trackIndices must also be true to call this.
738 * Overload for the no-auxdata case.
741void AuxVectorBase::moveAuxNoClear (size_t /*index*/, const void* /*p*/)
747 * @brief Swap indices and auxiliary data between two elements.
748 * @param aindex Index of the first element, in this container.
749 * @param bindex Index of the second element, in @c bcont.
750 * @param a Pointer to the first element.
751 * @param b Pointer to the second element.
752 * @param bcont Container holding the second element.
753 * (May be the same as this, but doesn't have to be.)
755 * This is the no-auxdata case; it is a no-op except for checking
759void AuxVectorBase::swapElementsAux (size_t /*aindex*/,
763 AuxVectorBase* /*bcont*/)
765 ATHCONTAINERS_ASSERT (!m_trackIndices);
770 * @brief Reset indices / reorder aux data after elements have been permuted.
771 * @param index Index in the container of the start of the range.
772 * @param beg Start of the range of elements to process.
773 * @param end End of the range of elements to process.
775 * Call this after some operation that has permuted the elements in the
776 * container (such as sort). The index information in the elements
777 * will be used to permute all auxiliary data in the same way.
778 * Finally, all the indices will be reset in the correct order.
780 * @c ForwardIterator should be an iterator over the @c DataVector
781 * (not a base iterator).
783template <class ForwardIterator>
785void AuxVectorBase::resortAux (size_t index,
789 // If the xAOD base classes are used, then they always report that
790 // static auxids are present. However, if the container is empty,
791 // these variables are not actually retrievable, which can cause
792 // an exception in the ResortAuxHelper ctor. Work around here.
793 if (beg==end) return;
795 // Forward to the appropriate specialization, depending on whether
796 // or not aux data is supported.
797 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
798 resortAux1 (typename AuxStore_traits<valtype>::flag(),
804 * @brief Reset indices / reorder aux data after elements have been permuted.
805 * @param index Index in the container of the start of the range.
806 * @param beg Start of the range of elements to process.
807 * @param end End of the range of elements to process.
809 * No-auxdata version; a no-op except for checking @c m_trackIndices.
811template <class ForwardIterator>
813void AuxVectorBase::resortAux1 (const std::false_type&,
815 ForwardIterator /*beg*/,
816 ForwardIterator /*end*/)
818 ATHCONTAINERS_ASSERT (!m_trackIndices);
823 * @brief Reset indices / reorder aux data after elements have been permuted.
824 * @param index Index in the container of the start of the range.
825 * @param beg Start of the range of elements to process.
826 * @param end End of the range of elements to process.
828 * Call this after some operation that has permuted the elements in the
829 * container (such as sort). The index information in the elements
830 * will be used to permute all auxiliary data in the same way.
831 * Finally, all the indices will be reset in the correct order.
835template <class ForwardIterator>
836void AuxVectorBase::resortAux1 (const std::true_type&,
841 if (!m_trackIndices) return;
842 if (!this->hasStore()) {
843 this->setIndices (beg, end, index);
846 if (!this->hasNonConstStore()) {
847 throw SG::ExcConstAuxData ("resortAux");
850 ResortAuxHelper h (end-beg, index, *this);
851 for (size_t i = 0; beg < end; ++beg, ++i)
852 h.resortElement (i, *beg);
856/// Helper to call @c getDataArray from @c ResortAuxHelper.
858void* AuxVectorBase::getDataArrayForResort (SG::auxid_t auxid)
860 return this->getDataArray (auxid);
864/// Helper to call @c setIndex from @c ResortAuxHelper.
866void AuxVectorBase::setIndexForResort (SG::AuxElement* elt, size_t i)
868 elt->setIndex (i, this);