1 // Dear emacs, this is -*- c++ -*-
3 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
6 * @file AthContainers/AuxElement.icc
7 * @author scott snyder <snyder@bnl.gov>
9 * @brief Base class for elements of a container that can have aux data.
13 #include "AthContainers/tools/likely.h"
14 #include "CxxUtils/checker_macros.h"
22 * @brief Default constructor.
25 ConstAuxElement::ConstAuxElement()
26 : m_container (nullptr)
32 * @brief Constructor with explicit container / index.
33 * @param container Container of which this element will be a part.
34 * @param index Index of this element within the container.
36 * This does not make any changes to aux data.
39 ConstAuxElement::ConstAuxElement (const SG::AuxVectorData* container,
41 : IAuxElement (index),
42 m_container (container)
48 * @brief Copy Constructor.
49 * @param other Object being copied.
51 * We do not copy the container/index --- the new object is not yet
54 * In the case of constructing an object with a private store,
55 * @c makePrivateStore will take care of copying the aux data.
58 ConstAuxElement::ConstAuxElement (const ConstAuxElement& /*other*/)
68 * Any private store is deleted.
71 ConstAuxElement::~ConstAuxElement()
73 if (ATHCONTAINERS_UNLIKELY (!noPrivateData()))
74 releasePrivateStoreForDtor();
79 * @brief Return the container holding this element.
82 const SG::AuxVectorData* ConstAuxElement::container() const
89 * @brief Set the index/container for this element.
90 * @param index The index of this object within the container.
91 * @param container The container holding this object.
92 * May be null if this object is being removed
95 * Usually this simply sets the index and container members
96 * of this object. However, in the case where this object has
97 * an associated private store, then we need to deal with
98 * releasing the store if the object is being added to a container,
99 * or making a new store if the object is being removed from a container.
102 void ConstAuxElement::setIndex (size_t index,
103 const SG::AuxVectorData* container)
105 if (ATHCONTAINERS_UNLIKELY (!noPrivateData())) {
106 // out-of-line piece, dealing with private store.
107 setIndexPrivate (index, container);
111 IAuxElement::setIndex (index);
112 m_container = container;
117 * @brief Fetch an aux data variable, as a const reference.
118 * @param name Name of the aux variable.
120 * This method has to translate from the aux data name to the internal
121 * representation each time it is called. Using this method
122 * inside of loops is discouraged; instead use the @c Accessor
123 * or @c ConstAccessor classes.
125 template <class T, class ALLOC>
126 typename ConstAccessor<T, ALLOC>::const_reference_type
127 ConstAuxElement::auxdata (const std::string& name) const
129 return ConstAccessor<T, ALLOC>(name, "")(*this);
134 * @brief Fetch an aux data variable, as a const reference.
135 * @param name Name of the aux variable.
136 * @param clsname The name of the associated class. May be blank.
138 * This method has to translate from the aux data name to the internal
139 * representation each time it is called. Using this method
140 * inside of loops is discouraged; instead use the @c Accessor
141 * or @c ConstAccessor classes.
143 template <class T, class ALLOC>
144 typename ConstAccessor<T, ALLOC>::const_reference_type
145 ConstAuxElement::auxdata (const std::string& name,
146 const std::string& clsname) const
148 return ConstAccessor<T, ALLOC>(name, clsname)(*this);
153 * @brief Fetch an aux data variable, as a const reference.
154 * @param name Name of the aux variable.
156 * This method has to translate from the aux data name to the internal
157 * representation each time it is called. Using this method
158 * inside of loops is discouraged; instead use the @c ConstAccessor class.
160 template <class T, class ALLOC>
161 typename ConstAccessor<T, ALLOC>::const_reference_type
162 ConstAuxElement::auxdataConst (const std::string& name) const
164 return ConstAccessor<T, ALLOC>(name, "")(*this);
169 * @brief Fetch an aux data variable, as a const reference.
170 * @param name Name of the aux variable.
171 * @param clsname The name of the associated class. May be blank.
173 * This method has to translate from the aux data name to the internal
174 * representation each time it is called. Using this method
175 * inside of loops is discouraged; instead use the @c ConstAccessor class.
177 template <class T, class ALLOC>
178 typename ConstAccessor<T, ALLOC>::const_reference_type
179 ConstAuxElement::auxdataConst (const std::string& name,
180 const std::string& clsname) const
182 return ConstAccessor<T, ALLOC>(name, clsname)(*this);
187 * @brief Check if an aux variable is available for reading
188 * @param name Name of the aux variable.
189 * @param clsname The name of the associated class. May be blank.
191 * This method has to translate from the aux data name to the internal
192 * representation each time it is called. Using this method
193 * inside of loops is discouraged; instead use the @c Accessor class.
195 template <class T, class ALLOC>
196 bool ConstAuxElement::isAvailable (const std::string& name,
197 const std::string& clsname /*= ""*/) const
199 return ConstAccessor<T, ALLOC>(name, clsname).isAvailable(*this);
204 * @brief Check if an aux variable is available for writing as a decoration.
205 * @param name Name of the aux variable.
206 * @param clsname The name of the associated class. May be blank.
208 * This method has to translate from the aux data name to the internal
209 * representation each time it is called. Using this method
210 * inside of loops is discouraged; instead use the @c Accessor class.
212 template <class T, class ALLOC>
213 bool ConstAuxElement::isAvailableWritableAsDecoration (const std::string& name,
214 const std::string& clsname /*= ""*/) const
216 return Decorator<T, ALLOC>(name, clsname).isAvailableWritable(*this);
221 * @brief Fetch an aux decoration, as a non-const reference.
222 * @param name Name of the aux variable.
223 * @param clsname The name of the associated class. May be blank.
225 * This method has to translate from the aux data name to the internal
226 * representation each time it is called. Using this method
227 * inside of loops is discouraged; instead use the @c Accessor class.
229 * If the container is locked, this will allow fetching only variables
230 * that do not yet exist (in which case they will be marked as decorations)
231 * or variables already marked as decorations.
233 template <class T, class ALLOC>
234 typename Decorator<T, ALLOC>::reference_type
235 ConstAuxElement::auxdecor (const std::string& name) const
237 return Decorator<T, ALLOC>(name, "")(*this);
242 * @brief Fetch an aux decoration, as a non-const reference.
243 * @param name Name of the aux variable.
244 * @param clsname The name of the associated class. May be blank.
246 * This method has to translate from the aux data name to the internal
247 * representation each time it is called. Using this method
248 * inside of loops is discouraged; instead use the @c Accessor class.
250 * If the container is locked, this will allow fetching only variables
251 * that do not yet exist (in which case they will be marked as decorations)
252 * or variables already marked as decorations.
254 template <class T, class ALLOC>
255 typename Decorator<T, ALLOC>::reference_type
256 ConstAuxElement::auxdecor (const std::string& name,
257 const std::string& clsname) const
259 return Decorator<T, ALLOC>(name, clsname)(*this);
263 //******************************************************************************
267 * @brief Default constructor.
270 AuxElement::AuxElement()
271 #ifdef ATHCONTAINERS_R21_COMPAT
279 * @brief Constructor with explicit container / index.
280 * @param container Container of which this element will be a part.
281 * @param index Index of this element within the container.
283 * This does not make any changes to aux data.
286 AuxElement::AuxElement (SG::AuxVectorData* container,
288 #ifdef ATHCONTAINERS_R21_COMPAT
289 : IAuxElement(index),
290 m_container (container)
292 : ConstAuxElement(container, index)
299 * @brief Copy Constructor.
300 * @param other Object being copied.
302 * We do not copy the container/index --- the new object is not yet
305 * In the case of constructing an object with a private store,
306 * @c makePrivateStore will take care of copying the aux data.
309 AuxElement::AuxElement ([[maybe_unused]] const AuxElement& other)
310 #ifdef ATHCONTAINERS_R21_COMPAT
314 : ConstAuxElement (other)
322 * @param other The object from which we're assigning.
324 * We don't copy container/index, as assignment doesn't change where
325 * this object is. However, if we have aux data, then we copy aux data
326 * if we're copying from an object that also has it; otherwise,
327 * if we're copying from an object with no aux data, then we clear ours.
330 AuxElement& AuxElement::operator= (const AuxElement& other)
332 this->assign (other);
339 * @param other The object from which we're assigning.
340 * @param warnUnlocked If true, then warn when we skip unlocked decorations.
342 * We don't copy container/index, as assignment doesn't change where
343 * this object is. However, if we have aux data, then we copy aux data
344 * if we're copying from an object that also has it; otherwise,
345 * if we're copying from an object with no aux data, then we clear ours.
348 void AuxElement::assign (const AuxElement& other,
349 bool warnUnlocked /*= false*/)
351 if (this != &other) {
352 if (this->container()) {
353 if (!other.container()) {
354 // Copying from an object with no aux data.
355 // Clear our aux data.
359 // Copying from an object with aux data.
360 // Copy the aux data too.
361 this->copyAux (other, warnUnlocked);
371 * Any private store is deleted.
374 AuxElement::~AuxElement()
376 #ifdef ATHCONTAINERS_R21_COMPAT
377 if (ATHCONTAINERS_UNLIKELY (!noPrivateData()))
378 releasePrivateStoreForDtor();
384 * @brief Return the container holding this element.
387 const SG::AuxVectorData* AuxElement::container() const
389 #ifdef ATHCONTAINERS_R21_COMPAT
392 return ConstAuxElement::container();
398 * @brief Return the container holding this element.
401 SG::AuxVectorData* AuxElement::container()
403 #ifdef ATHCONTAINERS_R21_COMPAT
406 SG::AuxVectorData* cont ATLAS_THREAD_SAFE = const_cast<SG::AuxVectorData*> (ConstAuxElement::container());
412 //******************************************************************************
416 * @brief Fetch an aux data variable, as a non-const reference.
417 * @param name Name of the aux variable.
418 * @param clsname The name of the associated class. May be blank.
420 * This method has to translate from the aux data name to the internal
421 * representation each time it is called. Using this method
422 * inside of loops is discouraged; instead use the @c Accessor class.
424 template <class T, class ALLOC>
425 typename Accessor<T, ALLOC>::reference_type
426 AuxElement::auxdata (const std::string& name)
428 return Accessor<T, ALLOC>(name, "")(*this);
433 * @brief Fetch an aux data variable, as a non-const reference.
434 * @param name Name of the aux variable.
435 * @param clsname The name of the associated class. May be blank.
437 * This method has to translate from the aux data name to the internal
438 * representation each time it is called. Using this method
439 * inside of loops is discouraged; instead use the @c Accessor class.
441 template <class T, class ALLOC>
442 typename Accessor<T, ALLOC>::reference_type
443 AuxElement::auxdata (const std::string& name,
444 const std::string& clsname)
446 return Accessor<T, ALLOC>(name, clsname)(*this);
451 * @brief Fetch an aux data variable, as a const reference.
452 * @param name Name of the aux variable.
454 * This method has to translate from the aux data name to the internal
455 * representation each time it is called. Using this method
456 * inside of loops is discouraged; instead use the @c Accessor
457 * or @c ConstAccessor classes.
459 template <class T, class ALLOC>
460 typename Accessor<T, ALLOC>::const_reference_type
461 AuxElement::auxdata (const std::string& name) const
463 return Accessor<T, ALLOC>(name, "")(*this);
468 * @brief Fetch an aux data variable, as a const reference.
469 * @param name Name of the aux variable.
470 * @param clsname The name of the associated class. May be blank.
472 * This method has to translate from the aux data name to the internal
473 * representation each time it is called. Using this method
474 * inside of loops is discouraged; instead use the @c Accessor
475 * or @c ConstAccessor classes.
477 template <class T, class ALLOC>
478 typename Accessor<T, ALLOC>::const_reference_type
479 AuxElement::auxdata (const std::string& name,
480 const std::string& clsname) const
482 return Accessor<T, ALLOC>(name, clsname)(*this);
487 * @brief Fetch an aux data variable, as a const reference.
488 * @param name Name of the aux variable.
490 * This method has to translate from the aux data name to the internal
491 * representation each time it is called. Using this method
492 * inside of loops is discouraged; instead use the @c ConstAccessor class.
494 template <class T, class ALLOC>
495 typename Accessor<T, ALLOC>::const_reference_type
496 AuxElement::auxdataConst (const std::string& name) const
498 return Accessor<T, ALLOC>(name, "")(*this);
503 * @brief Fetch an aux data variable, as a const reference.
504 * @param name Name of the aux variable.
505 * @param clsname The name of the associated class. May be blank.
507 * This method has to translate from the aux data name to the internal
508 * representation each time it is called. Using this method
509 * inside of loops is discouraged; instead use the @c ConstAccessor class.
511 template <class T, class ALLOC>
512 typename Accessor<T, ALLOC>::const_reference_type
513 AuxElement::auxdataConst (const std::string& name,
514 const std::string& clsname) const
516 return Accessor<T, ALLOC>(name, clsname)(*this);
521 * @brief Check if an aux variable is available for reading
522 * @param name Name of the aux variable.
523 * @param clsname The name of the associated class. May be blank.
525 * This method has to translate from the aux data name to the internal
526 * representation each time it is called. Using this method
527 * inside of loops is discouraged; instead use the @c Accessor class.
529 template <class T, class ALLOC>
530 bool AuxElement::isAvailable (const std::string& name,
531 const std::string& clsname /*= ""*/) const
533 return Accessor<T, ALLOC>(name, clsname).isAvailable(*this);
538 * @brief Check if an aux variable is available for writing
539 * @param name Name of the aux variable.
540 * @param clsname The name of the associated class. May be blank.
542 * This method has to translate from the aux data name to the internal
543 * representation each time it is called. Using this method
544 * inside of loops is discouraged; instead use the @c Accessor class.
546 template <class T, class ALLOC>
547 bool AuxElement::isAvailableWritable (const std::string& name,
548 const std::string& clsname /*= ""*/)
550 return Accessor<T, ALLOC>(name, clsname).isAvailableWritable(*this);
555 * @brief Check if an aux variable is available for writing as a decoration.
556 * @param name Name of the aux variable.
557 * @param clsname The name of the associated class. May be blank.
559 * This method has to translate from the aux data name to the internal
560 * representation each time it is called. Using this method
561 * inside of loops is discouraged; instead use the @c Accessor class.
563 template <class T, class ALLOC>
564 bool AuxElement::isAvailableWritableAsDecoration (const std::string& name,
565 const std::string& clsname /*= ""*/) const
567 return Decorator<T, ALLOC>(name, clsname).isAvailableWritable(*this);
572 * @brief Fetch an aux decoration, as a non-const reference.
573 * @param name Name of the aux variable.
574 * @param clsname The name of the associated class. May be blank.
576 * This method has to translate from the aux data name to the internal
577 * representation each time it is called. Using this method
578 * inside of loops is discouraged; instead use the @c Accessor class.
580 * If the container is locked, this will allow fetching only variables
581 * that do not yet exist (in which case they will be marked as decorations)
582 * or variables already marked as decorations.
584 template <class T, class ALLOC>
585 typename Decorator<T, ALLOC>::reference_type
586 AuxElement::auxdecor (const std::string& name) const
588 return Decorator<T, ALLOC>(name, "")(*this);
593 * @brief Fetch an aux decoration, as a non-const reference.
594 * @param name Name of the aux variable.
595 * @param clsname The name of the associated class. May be blank.
597 * This method has to translate from the aux data name to the internal
598 * representation each time it is called. Using this method
599 * inside of loops is discouraged; instead use the @c Accessor class.
601 * If the container is locked, this will allow fetching only variables
602 * that do not yet exist (in which case they will be marked as decorations)
603 * or variables already marked as decorations.
605 template <class T, class ALLOC>
606 typename Decorator<T, ALLOC>::reference_type
607 AuxElement::auxdecor (const std::string& name,
608 const std::string& clsname) const
610 return Decorator<T, ALLOC>(name, clsname)(*this);
615 * @brief Create a new private store for this object and copy aux data.
616 * @param other The object from which aux data should be copied.
617 * @param warnUnlocked If true, then warn when we skip unlocked decorations.
619 * @c ExcBadPrivateStore will be thrown if this object is already
620 * associated with a store.
622 * If @c other is an object that has aux data, then those data will
623 * be copied; otherwise, nothing will be done.
627 void AuxElement::makePrivateStore (const U1& other,
628 bool warnUnlocked /*=false*/)
630 // Dispatch to the proper overload depending on whether or not
631 // other derives from AuxElement.
632 makePrivateStore1 (&other, warnUnlocked);
637 * @brief Create a new private store for this object and copy aux data.
638 * @param other The object from which aux data should be copied.
639 * @param warnUnlocked If true, then warn when we skip unlocked decorations.
641 * @c ExcBadPrivateStore will be thrown if this object is already
642 * associated with a store.
644 * If @c other is an object that has aux data, then those data will
645 * be copied; otherwise, nothing will be done.
649 void AuxElement::makePrivateStore (const U1* other,
650 bool warnUnlocked /*=false*/)
652 // Dispatch to the proper overload depending on whether or not
653 // other derives from AuxElement.
654 makePrivateStore1 (other, warnUnlocked);
659 * @brief Synonym for @c setStore with @c IConstAuxStore.
660 * @param store The new store.
663 void AuxElement::setConstStore (const SG::IConstAuxStore* store)
670 * @brief Synonym for @c setStore with @c IAuxStore.
671 * @param store The new store.
674 void AuxElement::setNonConstStore (SG::IAuxStore* store)
681 * @brief Return true if index tracking is enabled for this object.
683 * Always returns true. Included here to be consistent with AuxVectorBase
684 * when standalone objects may be used as template parameters.
687 bool AuxElement::trackIndices() const
694 * @brief Set the index/container for this element.
695 * @param index The index of this object within the container.
696 * @param container The container holding this object.
697 * May be null if this object is being removed
700 * Usually this simply sets the index and container members
701 * of this object. However, in the case where this object has
702 * an associated private store, then we need to deal with
703 * releasing the store if the object is being added to a container,
704 * or making a new store if the object is being removed from a container.
707 void AuxElement::setIndex (size_t index, SG::AuxVectorData* container)
709 #ifdef ATHCONTAINERS_R21_COMPAT
710 if (ATHCONTAINERS_UNLIKELY (!noPrivateData())) {
711 // out-of-line piece, dealing with private store.
712 setIndexPrivate (index, container);
716 IAuxElement::setIndex (index);
717 m_container = container;
719 ConstAuxElement::setIndex (index, container);
725 * @brief Create a new private store for this object and copy aux data.
726 * @param other The object from which aux data should be copied.
728 * @c ExcBadPrivateStore will be thrown if this object is already
729 * associated with a store.
731 * This overload handles the case where @c other does not have aux data.
734 void AuxElement::makePrivateStore1 (const void*, bool)