2 Copyright (C) 2002-2024 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.
20 bool AuxVectorBase::trackIndices() const
22 return m_trackIndices;
27 * @brief Synonym for @c setStore with @c IConstAuxStore.
28 * @param store The new store.
31 void AuxVectorBase::setConstStore (const SG::IConstAuxStore* store)
38 * @brief Synonym for @c setStore with @c IAuxStore.
39 * @param store The new store.
42 void 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.
55 bool 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.
71 AuxVectorBase::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.
87 AuxVectorBase::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.
107 AuxVectorBase::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.
128 AuxVectorBase::const_span<T>
129 AuxVectorBase::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
156 AuxVectorBase::span<T>
157 AuxVectorBase::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.
178 AuxVectorBase::const_span<T>
179 AuxVectorBase::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.
204 AuxVectorBase::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.
220 void 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).
239 template <class ForwardIterator>
241 void 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
262 template <class ForwardIterator>
264 void 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.
283 template <class ForwardIterator>
284 void 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).
307 template <class ForwardIterator>
309 void 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
325 template <class ForwardIterator>
327 void 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.
340 template <class ForwardIterator>
341 void 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).
360 template <class ForwardIterator>
361 void 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.
379 template <class ForwardIterator>
381 void 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.
396 template <class ForwardIterator>
397 void 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.
418 void 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.
434 AuxVectorBase::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.
448 void 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.
463 void 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).
496 void 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.
517 void 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).
553 void 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.
583 * Overload for the no-auxdata case.
587 AuxVectorBase::moveAux (size_t /*index*/,
589 bool /*clear = false*/,
590 bool /*skipDestClear = false*/)
592 ATHCONTAINERS_ASSERT (!m_trackIndices);
597 * @brief Set index on a range of elements and copy auxiliary data.
598 * @param index Container index at which the first new element is being added.
599 * @param beg The start of the range of new elements.
600 * @param end The end of the range of new elements.
601 * @param clear If true, then any auxiliary data initially associated
602 * with the elements are cleared after being copied.
603 * @param skipDestClear Normally, if the elements do not have auxiliary data,
604 * then the variables of the destination are cleared.
605 * If this flag is true, then this clear is skipped.
606 * This can be appropriate as part of a push_back,
607 * where the destination is already known to be clear.
609 * The elements in the range are being a added to the container at @c index.
610 * If the new elements have associated auxiliary data,
611 * copy it to the container starting at @c index.
612 * Then set the container / index on the elements in the range.
614 * @c ForwardIterator should be an iterator over the @c DataVector
615 * (not a base iterator).
617 template <class ForwardIterator>
619 AuxVectorBase::moveAux (size_t index, ForwardIterator beg, ForwardIterator end,
620 bool clear /*= false*/,
621 bool skipDestClear /*= false*/)
623 // Forward to the appropriate specialization, depending on whether
624 // or not aux data is supported.
625 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
626 moveAux1 (typename AuxStore_traits<valtype>::flag(),
627 index, beg, end, clear, skipDestClear);
632 * @brief Set index on a range of elements and copy auxiliary data.
633 * @param index Container index at which the first new element is being added.
634 * @param beg The start of the range of new elements.
635 * @param end The end of the range of new elements.
636 * @param clear If true, then any auxiliary data initially associated
637 * with the elements are cleared after being copied.
638 * @param skipDestClear Normally, if the elements do not have auxiliary data,
639 * then the variables of the destination are cleared.
640 * If this flag is true, then this clear is skipped.
641 * This can be appropriate as part of a push_back,
642 * where the destination is already known to be clear.
644 * No-auxdata version; a no-op except for checking @c m_trackIndices.
646 template <class ForwardIterator>
648 void AuxVectorBase::moveAux1 (const std::false_type&,
650 ForwardIterator /*beg*/,
651 ForwardIterator /*end*/,
652 bool /*clear = false*/,
653 bool /*skipDestClear = false*/)
655 ATHCONTAINERS_ASSERT (!m_trackIndices);
660 * @brief Set index on a range of elements and copy auxiliary data.
661 * @param index Container index at which the first new element is being added.
662 * @param beg The start of the range of new elements.
663 * @param end The end of the range of new elements.
664 * @param clear If true, then any auxiliary data initially associated
665 * with the elements are cleared after being copied.
666 * @param skipDestClear Normally, if the elements do not have auxiliary data,
667 * then the variables of the destination are cleared.
668 * If this flag is true, then this clear is skipped.
669 * This can be appropriate as part of a push_back,
670 * where the destination is already known to be clear.
672 * The elements in the range are being a added to the container at @c index.
673 * If the new elements have associated auxiliary data,
674 * copy it to the container starting at @c index.
675 * Then set the container / index on the elements in the range.
679 template <class ForwardIterator>
680 void AuxVectorBase::moveAux1 (const std::true_type&,
684 bool clear /*= false*/,
685 bool skipDestClear /*= false*/)
691 this->moveAux (index, *beg, clear, skipDestClear);
699 * @brief Swap indices and auxiliary data between two elements.
700 * @param aindex Index of the first element, in this container.
701 * @param bindex Index of the second element, in @c bcont.
702 * @param a Pointer to the first element.
703 * @param b Pointer to the second element.
704 * @param bcont Container holding the second element.
705 * (May be the same as this, but doesn't have to be.)
707 * This is the no-auxdata case; it is a no-op except for checking
711 void AuxVectorBase::swapElementsAux (size_t /*aindex*/,
715 AuxVectorBase* /*bcont*/)
717 ATHCONTAINERS_ASSERT (!m_trackIndices);
722 * @brief Reset indices / reorder aux data after elements have been permuted.
723 * @param index Index in the container of the start of the range.
724 * @param beg Start of the range of elements to process.
725 * @param end End of the range of elements to process.
727 * Call this after some operation that has permuted the elements in the
728 * container (such as sort). The index information in the elements
729 * will be used to permute all auxiliary data in the same way.
730 * Finally, all the indices will be reset in the correct order.
732 * @c ForwardIterator should be an iterator over the @c DataVector
733 * (not a base iterator).
735 template <class ForwardIterator>
737 void AuxVectorBase::resortAux (size_t index,
741 // If the xAOD base classes are used, then they always report that
742 // static auxids are present. However, if the container is empty,
743 // these variables are not actually retrievable, which can cause
744 // an exception in the ResortAuxHelper ctor. Work around here.
745 if (beg==end) return;
747 // Forward to the appropriate specialization, depending on whether
748 // or not aux data is supported.
749 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
750 resortAux1 (typename AuxStore_traits<valtype>::flag(),
756 * @brief Reset indices / reorder aux data after elements have been permuted.
757 * @param index Index in the container of the start of the range.
758 * @param beg Start of the range of elements to process.
759 * @param end End of the range of elements to process.
761 * No-auxdata version; a no-op except for checking @c m_trackIndices.
763 template <class ForwardIterator>
765 void AuxVectorBase::resortAux1 (const std::false_type&,
767 ForwardIterator /*beg*/,
768 ForwardIterator /*end*/)
770 ATHCONTAINERS_ASSERT (!m_trackIndices);
775 * @brief Reset indices / reorder aux data after elements have been permuted.
776 * @param index Index in the container of the start of the range.
777 * @param beg Start of the range of elements to process.
778 * @param end End of the range of elements to process.
780 * Call this after some operation that has permuted the elements in the
781 * container (such as sort). The index information in the elements
782 * will be used to permute all auxiliary data in the same way.
783 * Finally, all the indices will be reset in the correct order.
787 template <class ForwardIterator>
788 void AuxVectorBase::resortAux1 (const std::true_type&,
793 if (!m_trackIndices) return;
794 if (!this->hasStore()) {
795 this->setIndices (beg, end, index);
798 if (!this->hasNonConstStore()) {
799 throw SG::ExcConstAuxData ("resortAux");
802 ResortAuxHelper h (end-beg, index, *this);
803 for (size_t i = 0; beg < end; ++beg, ++i)
804 h.resortElement (i, *beg);
808 /// Helper to call @c getDataArray from @c ResortAuxHelper.
810 void* AuxVectorBase::getDataArrayForResort (SG::auxid_t auxid)
812 return this->getDataArray (auxid);
816 /// Helper to call @c setIndex from @c ResortAuxHelper.
818 void AuxVectorBase::setIndexForResort (SG::AuxElement* elt, size_t i)
820 elt->setIndex (i, this);