2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 * @file AthLinks/GenericElementLinkBase.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Generic base class for ElementLinks.
17 * @brief Test the index validity.
18 * @returns True if the index is not valid (in default state).
20 template <class INDEXING_POLICY>
23 GenericElementLinkBase<INDEXING_POLICY>::isDefaultIndex() const
25 return ! INDEXING_POLICY::isValid (m_index);
30 * @brief Test to see if this link has a cached element pointer.
32 template <class INDEXING_POLICY>
35 GenericElementLinkBase<INDEXING_POLICY>::hasCachedElement() const
37 return m_element.isValid();
42 * @brief Test to see if this link is in the default state.
44 template <class INDEXING_POLICY>
47 GenericElementLinkBase<INDEXING_POLICY>::isDefault() const
49 return m_proxy.isDefault() && !hasCachedElement() && isDefaultIndex();
54 * @brief Return the index of the link.
56 template <class INDEXING_POLICY>
58 typename GenericElementLinkBase<INDEXING_POLICY>::index_type
59 GenericElementLinkBase<INDEXING_POLICY>::index() const
61 return INDEXING_POLICY::storedToExternal (m_index);
66 * @brief Return the SG key that we reference, as a string.
68 * Returns a null string on failure.
70 template <class INDEXING_POLICY>
72 const typename GenericElementLinkBase<INDEXING_POLICY>::ID_type&
73 GenericElementLinkBase<INDEXING_POLICY>::dataID() const
75 return m_proxy.dataID();
80 * @brief Return the SG key that we reference, as a hash.
82 * Returns 0 on failure.
84 template <class INDEXING_POLICY>
86 typename GenericElementLinkBase<INDEXING_POLICY>::sgkey_t
87 GenericElementLinkBase<INDEXING_POLICY>::key() const
94 * @brief Return the data source for this reference.
96 template <class INDEXING_POLICY>
99 GenericElementLinkBase<INDEXING_POLICY>::source() const
101 return m_proxy.source();
106 * @brief Return the SG proxy for the container holding this element.
108 * If this is a null link, we return 0.
109 * If we're directly referencing an object that's not in StoreGate,
110 * either return 0 or throw @c ExcPointerNotInSG, depending
111 * on @c nothrow. Otherwise, return the proxy for the object
114 template <class INDEXING_POLICY>
117 GenericElementLinkBase<INDEXING_POLICY>::proxy() const
119 return m_proxy.proxy(true);
124 * @brief Reset the link to a null state.
126 template <class INDEXING_POLICY>
128 void GenericElementLinkBase<INDEXING_POLICY>::reset ()
133 INDEXING_POLICY::reset (m_index);
138 * @brief Finish initialization after link has been read.
139 * @param sg Associated store.
141 * This should be called after a link has been read by root
142 * in order to set the proxy pointer.
145 * If @c sg is 0, then we use the global default store.
147 template <class INDEXING_POLICY>
150 GenericElementLinkBase<INDEXING_POLICY>::toTransient (IProxyDict* sg /*= 0*/)
152 m_proxy.toTransient (m_key, sg);
159 * @brief Prepare this link for writing.
161 * This method should be called before trying to write the link with root.
162 * It will make sure the persistent fields of the link are valid.
163 * It will also perform remapping if needed.
165 * Will return true on success. Will return false if either the container
166 * or the element index has not been specified. Will throw
167 * @c ExcPointerNotInSG if the link is referencing a container that
170 template <class INDEXING_POLICY>
173 GenericElementLinkBase<INDEXING_POLICY>::toPersistent()
175 if (isDefault()) return true;
176 if (m_proxy.isDefault() || isDefaultIndex()) return false;
177 if (m_proxy.toPersistent (m_key, m_index))
184 * @brief Adjust for thinning.
186 * If this link points to a container that has been thinned,
187 * it will be adjusted accordingly.
189 * Returns @c true if the link was changed; @c false otherwise.
191 template <class INDEXING_POLICY>
193 bool GenericElementLinkBase<INDEXING_POLICY>::thin()
195 return thin (SG::getThinningCache());
200 * @brief Adjust for thinning.
201 * @param thinningCache Thinning cache for the current stream
204 * If this link points to a container that has been thinned,
205 * it will be adjusted accordingly.
207 * Returns @c true if the link was changed; @c false otherwise.
209 template <class INDEXING_POLICY>
211 bool GenericElementLinkBase<INDEXING_POLICY>::thin (const SG::ThinningCache* thinningCache)
213 return thin1 (m_index, thinningCache);
218 * @brief Adjust for thinning.
220 * If this link points to a container that has been thinned,
221 * it will be adjusted accordingly.
222 * @param Index of the element.
223 * @param thinningCache Thinning cache for the current stream
226 * Returns @c true if the link was changed; @c false otherwise.
228 * This overload will be used for the case where thinning is supported:
229 * the index can be interconverted with size_t.
231 template <class INDEXING_POLICY>
232 template <class INDEX>
233 requires (std::convertible_to<INDEX, size_t> &&
234 std::convertible_to<size_t, INDEX>)
236 bool GenericElementLinkBase<INDEXING_POLICY>::thin1 (INDEX& persIndex,
237 const SG::ThinningCache* thinningCache)
239 bool ret1 = toPersistent();
240 size_t index = static_cast<size_t>(persIndex);
241 bool ret = m_proxy.thin (m_key, index, thinningCache);
243 persIndex = static_cast<stored_index_type>(index);
251 * @brief Adjust for thinning.
253 * If this link points to a container that has been thinned,
254 * it will be adjusted accordingly.
255 * @param Index of the element.
256 * @param thinningCache Thinning cache for the current stream
259 * Returns @c true if the link was changed; @c false otherwise.
261 * This overload will be used for the case where thinning is not supported.
263 template <class INDEXING_POLICY>
264 template <class INDEX>
265 requires (!(std::convertible_to<INDEX, size_t> &&
266 std::convertible_to<size_t, INDEX>))
268 bool GenericElementLinkBase<INDEXING_POLICY>::thin1 (INDEX& /*persIndex*/,
269 const SG::ThinningCache* /*thinningCache*/)
271 throwExcBadThinning (this->proxy() ? this->proxy()->clID() : CLID_NULL,
272 this->dataID(), this->key());
277 * @brief Default constructor. Makes a null link.
279 template <class INDEXING_POLICY>
281 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase()
285 INDEXING_POLICY::reset (m_index);
290 * @brief Construct a link from a string key and an index.
291 * @param dataID Key of the object.
292 * @param link_clid CLID of the link being set.
293 * @param elemID The index of the element within the container.
294 * @param sg Associated store.
296 * If @c sg is 0, we take the global default.
298 template <class INDEXING_POLICY>
300 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
301 (const ID_type& dataID,
303 const index_type& elemID,
305 : m_index (static_cast<stored_index_type>(elemID)),
308 m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
313 * @brief Construct a link from a hashed key and an index.
314 * @param key Hashed key of the object.
315 * @param link_clid CLID of the link being set.
316 * @param elemID The index of the element within the container.
317 * @param sg Associated store.
319 * If @c sg is 0, we take the global default.
321 template <class INDEXING_POLICY>
323 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
326 const index_type& elemID,
329 m_index (static_cast<stored_index_type>(elemID)),
332 m_proxy.toIdentifiedObject (key, link_clid, sg);
337 * @brief Construct a link from a string key, index, AND pointer to element.
338 * @param dataID Key of the object.
339 * @param link_clid CLID of the link being set.
340 * @param elemID The index of the element within the container.
341 * @param elt Pointer to the element.
342 * @param sg Associated store.
344 * USE CAREFULLY: no coherency checks, we just trust you!
346 * If @c sg is 0, we take the global default.
348 template <class INDEXING_POLICY>
350 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
351 (const ID_type& dataID,
353 const index_type& elemID,
354 const ElementType& elt,
356 : m_index (static_cast<stored_index_type>(elemID)),
359 m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
364 * @brief Construct a link from a hashed key, index, AND pointer to element.
365 * @param key Hashed key of the object.
366 * @param link_clid CLID of the link being set.
367 * @param elemID The index of the element within the container.
368 * @param elt Pointer to the element.
369 * @param sg Associated store.
371 * USE CAREFULLY: no coherency checks, we just trust you!
373 * If @c sg is 0, we take the global default.
375 template <class INDEXING_POLICY>
377 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
380 const index_type& elemID,
381 const ElementType& elt,
384 m_index (static_cast<stored_index_type>(elemID)),
387 m_proxy.toIdentifiedObject (key, link_clid, sg);
392 * @brief Construct a link from an index and pointer to the container.
393 * @param obj Pointer to the container (storable).
394 * @param link_clid CLID of the link being set.
395 * @param elemID The index of the element within the container.
396 * @param sg Associated store.
398 * If @c sg is 0, we take the global default.
400 template <class INDEXING_POLICY>
402 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
403 (const_pointer_t obj,
405 const index_type& elemID,
407 : m_index (static_cast<stored_index_type>(elemID)),
410 m_key = m_proxy.toStorableObject (obj, link_clid, sg);
415 * @brief Construct a link from another link, changing the index.
416 * @param other The source link.
417 * @param elemID The index for the new link.
419 * The index being constructed will reference the same container
420 * as @c other, but it will refer to element @c elemID.
422 template <class INDEXING_POLICY>
424 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
425 (const GenericElementLinkBase& other,
426 const index_type& elemID)
427 : m_key (other.m_key),
428 m_index (static_cast<stored_index_type>(elemID)),
429 m_proxy (other.m_proxy),
436 * @brief Construct a link from a DataLink and an index.
437 * @param dlink Link to the container.
438 * @param index The index of the element within the container.
440 template <class INDEXING_POLICY>
442 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
443 (const DataLinkBase& dlink,
444 const index_type& index)
445 : m_key (dlink.key()),
446 m_index (static_cast<stored_index_type>(index)),
447 m_proxy (dlink.m_proxy),
450 if (dlink.isDefault()) {
451 INDEXING_POLICY::reset (m_index);
457 * @brief Constructor from a link referencing a different type.
458 * @param other The object from which to copy.
460 * @c FROM_TRAITS is the @c ElementLinkTraits class for @c other;
461 * @c TO_TRAITS is the traits class for this object.
462 * The actual pointer values are not used, just the types are used.
463 * Default conversions for the storable pointer (i.e., derived->base)
466 template <class INDEXING_POLICY>
467 template <class OTHER_INDEXING_POLICY, class FROM_TRAITS, class TO_TRAITS>
468 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
469 (const GenericElementLinkBase<OTHER_INDEXING_POLICY>& other,
472 : m_key (other.m_key),
473 m_index (other.m_index),
474 m_proxy (other.m_proxy,
475 (typename FROM_TRAITS::Storable*)0,
476 (typename TO_TRAITS::Storable*)0),
477 m_element (other.m_element)
479 // The TRAITS template args are redundant here with the indexing policy args,
480 // but we need this signature for the non-templated ElementLinkBase case.
485 * @brief Return a pointer to the currently-referenced container object.
486 * @param castfn Function to do the cast from data proxy to object.
487 * If 0, use a dynamic cast.
488 * @param clid The CLID of the desired object.
489 * This is used to determine how the returned pointer
490 * is to be converted.
491 * @param isConst True if the returned object will be treated as const.
492 * @return A pointer to an object of the type given by @a clid,
493 * or null on a failure (or if the reference is null).
495 template <class INDEXING_POLICY>
497 void* GenericElementLinkBase<INDEXING_POLICY>::storableBase
498 (castfn_t* castfn, const CLID& clid, bool isConst) const
500 return m_proxy.storableBase (castfn, clid, isConst);
505 * @brief Set the container referenced by the link to @c data.
506 * @param data Pointer to the new container.
507 * @param link_clid CLID of the link being set.
508 * @param replace True if we can change an existing link.
509 * @param sg Associated store.
510 * @returns True if the link was changed.
512 * If the link is already set, this will return false and leave the
513 * link unchanged unless @c replace is set. The @c replace argument
514 * should be set if the element is now in a new storable container;
515 * e.g. element ptr has been put in a new view container.
517 * If @c sg is 0, then we take the store from whatever the link's currently
518 * set to. If the link has no current store, then we take the global
521 template <class INDEXING_POLICY>
523 bool GenericElementLinkBase<INDEXING_POLICY>::setStorableObject
524 (const_pointer_t data,
529 if (!m_proxy.isDefault()) {
530 if (!replace) return false;
531 INDEXING_POLICY::reset (m_index);
534 m_key = m_proxy.toStorableObject (data, link_clid, sg);
540 * @brief Set the to an element given by index and pointer to container.
541 * @param obj Pointer to the container (storable).
542 * @param link_clid CLID of the link being set.
543 * @param elemID The index of the element within the container.
544 * @param sg Associated store.
545 * @returns True if the link was changed.
547 * If the link is already set, this will return false and leave the
550 * If @c sg is 0, then we take the store from whatever the link's currently
551 * set to. If the link has no current store, then we take the global
554 template <class INDEXING_POLICY>
556 bool GenericElementLinkBase<INDEXING_POLICY>::toIndexedElement
557 (const_pointer_t obj,
559 const index_type& elemID,
562 if (m_proxy.isDefault() && isDefaultIndex() && !hasCachedElement()) {
563 m_key = m_proxy.toStorableObject (obj, link_clid, sg);
564 m_index = static_cast<stored_index_type>(elemID);
573 * @brief Set the link to an element given by string key and index.
574 * @param dataID Key of the object.
575 * @param link_clid CLID of the link being set.
576 * @param elemID The index of the element within the container.
577 * @param sg Associated store.
579 * If @c sg is 0, then we take the store from whatever the link's currently
580 * set to. If the link has no current store, then we take the global
583 template <class INDEXING_POLICY>
585 void GenericElementLinkBase<INDEXING_POLICY>::resetWithKeyAndIndex
586 (const ID_type& dataID,
588 const index_type& elemID,
591 m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
592 m_index = static_cast<stored_index_type>(elemID);
598 * @brief Set the link to an element given by string key and index.
599 * @param key Hashed key of the object.
600 * @param link_clid CLID of the link being set.
601 * @param elemID The index of the element within the container.
602 * @param sg Associated store.
604 * If @c sg is 0, then we take the store from whatever the link's currently
605 * set to. If the link has no current store, then we take the global
608 template <class INDEXING_POLICY>
610 void GenericElementLinkBase<INDEXING_POLICY>::resetWithKeyAndIndex
613 const index_type& elemID,
617 m_proxy.toIdentifiedObject (key, link_clid, sg);
618 m_index = static_cast<stored_index_type>(elemID);
624 * @brief Set the index part of the link.
625 * @param index New index value.
627 template <class INDEXING_POLICY>
630 GenericElementLinkBase<INDEXING_POLICY>::setIndex (const index_type& index)
632 m_index = static_cast<stored_index_type>(index);
637 * @brief Return the stored representation of the link index.
639 template <class INDEXING_POLICY>
641 const typename GenericElementLinkBase<INDEXING_POLICY>::stored_index_type&
642 GenericElementLinkBase<INDEXING_POLICY>::storedIndex() const
649 * @brief Set the cached element stored in the link.
650 * @param elt New value for the cached element.
652 template <class INDEXING_POLICY>
655 GenericElementLinkBase<INDEXING_POLICY>::setCachedElement (const ElementType& elt) const
662 * @brief Set the cached element stored in the link.
663 * @param elt New value for the cached element.
665 template <class INDEXING_POLICY>
668 GenericElementLinkBase<INDEXING_POLICY>::storeCachedElement (const ElementType& elt)
670 m_element.store (elt);
675 * @brief Retrieve the cached element from the link.
676 * @param elt[out] The cached element.
677 * @returns True if an element was cached; false otherwise.
679 * @c elt is left unmodified if there is no cached element.
681 template <class INDEXING_POLICY>
684 GenericElementLinkBase<INDEXING_POLICY>::getCachedElement (ElementConstPointer& elt) const
686 if (m_element.isValid()) {
687 elt = m_element.ptr();
695 * @brief Return the internal proxy holder object.
697 template <class INDEXING_POLICY>
699 const SG::DataProxyHolder&
700 GenericElementLinkBase<INDEXING_POLICY>::proxyHolder() const