ATLAS Offline Software
GenericElementLinkBase.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthLinks/GenericElementLinkBase.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Apr, 2014
8  * @brief Generic base class for ElementLinks.
9  */
10 
11 
12 
13 namespace SG {
14 
15 
16 /**
17  * @brief Test the index validity.
18  * @returns True if the index is not valid (in default state).
19  */
20 template <class INDEXING_POLICY>
21 inline
22 bool
23 GenericElementLinkBase<INDEXING_POLICY>::isDefaultIndex() const
24 {
25  return ! INDEXING_POLICY::isValid (m_index);
26 }
27 
28 
29 /**
30  * @brief Test to see if this link has a cached element pointer.
31  */
32 template <class INDEXING_POLICY>
33 inline
34 bool
35 GenericElementLinkBase<INDEXING_POLICY>::hasCachedElement() const
36 {
37  return m_element.isValid();
38 }
39 
40 
41 /**
42  * @brief Test to see if this link is in the default state.
43  */
44 template <class INDEXING_POLICY>
45 inline
46 bool
47 GenericElementLinkBase<INDEXING_POLICY>::isDefault() const
48 {
49  return m_proxy.isDefault() && !hasCachedElement() && isDefaultIndex();
50 }
51 
52 
53 /**
54  * @brief Return the index of the link.
55  */
56 template <class INDEXING_POLICY>
57 inline
58 typename GenericElementLinkBase<INDEXING_POLICY>::index_type
59 GenericElementLinkBase<INDEXING_POLICY>::index() const
60 {
61  return INDEXING_POLICY::storedToExternal (m_index);
62 }
63 
64 
65 /**
66  * @brief Return the SG key that we reference, as a string.
67  *
68  * Returns a null string on failure.
69  */
70 template <class INDEXING_POLICY>
71 inline
72 const typename GenericElementLinkBase<INDEXING_POLICY>::ID_type&
73 GenericElementLinkBase<INDEXING_POLICY>::dataID() const
74 {
75  return m_proxy.dataID();
76 }
77 
78 
79 /**
80  * @brief Return the SG key that we reference, as a hash.
81  *
82  * Returns 0 on failure.
83  */
84 template <class INDEXING_POLICY>
85 inline
86 typename GenericElementLinkBase<INDEXING_POLICY>::sgkey_t
87 GenericElementLinkBase<INDEXING_POLICY>::key() const
88 {
89  return m_key;
90 }
91 
92 
93 /**
94  * @brief Return the data source for this reference.
95  */
96 template <class INDEXING_POLICY>
97 inline
98 IProxyDict*
99 GenericElementLinkBase<INDEXING_POLICY>::source() const
100 {
101  return m_proxy.source();
102 }
103 
104 
105 /**
106  * @brief Return the SG proxy for the container holding this element.
107  *
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
112  * we're referencing.
113  */
114 template <class INDEXING_POLICY>
115 inline
116 const SG::DataProxy*
117 GenericElementLinkBase<INDEXING_POLICY>::proxy() const
118 {
119  return m_proxy.proxy(true);
120 }
121 
122 
123 /**
124  * @brief Reset the link to a null state.
125  */
126 template <class INDEXING_POLICY>
127 inline
128 void GenericElementLinkBase<INDEXING_POLICY>::reset ()
129 {
130  m_proxy.clear();
131  m_key = 0;
132  m_element.reset();
133  INDEXING_POLICY::reset (m_index);
134 }
135 
136 
137 /**
138  * @brief Finish initialization after link has been read.
139  * @param sg Associated store.
140  *
141  * This should be called after a link has been read by root
142  * in order to set the proxy pointer.
143  * Returns true.
144  *
145  * If @c sg is 0, then we use the global default store.
146  */
147 template <class INDEXING_POLICY>
148 inline
149 bool
150 GenericElementLinkBase<INDEXING_POLICY>::toTransient (IProxyDict* sg /*= 0*/)
151 {
152  m_proxy.toTransient (m_key, sg);
153  m_element.reset();
154  return true;
155 }
156 
157 
158 /**
159  * @brief Prepare this link for writing.
160  *
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.
164  *
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
168  * is not in SG.
169  */
170 template <class INDEXING_POLICY>
171 inline
172 bool
173 GenericElementLinkBase<INDEXING_POLICY>::toPersistent()
174 {
175  if (isDefault()) return true;
176  if (m_proxy.isDefault() || isDefaultIndex()) return false;
177  if (m_proxy.toPersistent (m_key, m_index))
178  m_element.reset();
179  return true;
180 }
181 
182 
183 /**
184  * @brief Adjust for thinning.
185  *
186  * If this link points to a container that has been thinned,
187  * it will be adjusted accordingly.
188  *
189  * Returns @c true if the link was changed; @c false otherwise.
190  */
191 template <class INDEXING_POLICY>
192 inline
193 bool GenericElementLinkBase<INDEXING_POLICY>::thin()
194 {
195  return thin (SG::getThinningCache());
196 }
197 
198 
199 /**
200  * @brief Adjust for thinning.
201  * @param thinningCache Thinning cache for the current stream
202  * (may be null).
203  *
204  * If this link points to a container that has been thinned,
205  * it will be adjusted accordingly.
206  *
207  * Returns @c true if the link was changed; @c false otherwise.
208  */
209 template <class INDEXING_POLICY>
210 inline
211 bool GenericElementLinkBase<INDEXING_POLICY>::thin (const SG::ThinningCache* thinningCache)
212 {
213  return thin1 (m_index, thinningCache);
214 }
215 
216 
217 /**
218  * @brief Adjust for thinning.
219  *
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
224  * (may be null).
225  *
226  * Returns @c true if the link was changed; @c false otherwise.
227  *
228  * This overload will be used for the case where thinning is supported:
229  * the index can be interconverted with size_t.
230  */
231 template <class INDEXING_POLICY>
232 template <class INDEX>
233 requires (std::convertible_to<INDEX, size_t> &&
234  std::convertible_to<size_t, INDEX>)
235 inline
236 bool GenericElementLinkBase<INDEXING_POLICY>::thin1 (INDEX& persIndex,
237  const SG::ThinningCache* thinningCache)
238 {
239  bool ret1 = toPersistent();
240  size_t index = static_cast<size_t>(persIndex);
241  bool ret = m_proxy.thin (m_key, index, thinningCache);
242  if (ret) {
243  persIndex = static_cast<stored_index_type>(index);
244  m_element.reset();
245  }
246  return ret1 || ret;
247 }
248 
249 
250 /**
251  * @brief Adjust for thinning.
252  *
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
257  * (may be null).
258  *
259  * Returns @c true if the link was changed; @c false otherwise.
260  *
261  * This overload will be used for the case where thinning is not supported.
262  */
263 template <class INDEXING_POLICY>
264 template <class INDEX>
265 requires (!(std::convertible_to<INDEX, size_t> &&
266  std::convertible_to<size_t, INDEX>))
267 inline
268 bool GenericElementLinkBase<INDEXING_POLICY>::thin1 (INDEX& /*persIndex*/,
269  const SG::ThinningCache* /*thinningCache*/)
270 {
271  throwExcBadThinning (this->proxy() ? this->proxy()->clID() : CLID_NULL,
272  this->dataID(), this->key());
273 }
274 
275 
276 /**
277  * @brief Default constructor. Makes a null link.
278  */
279 template <class INDEXING_POLICY>
280 inline
281 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase()
282  : m_key(0),
283  m_element()
284 {
285  INDEXING_POLICY::reset (m_index);
286 }
287 
288 
289 /**
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.
295  *
296  * If @c sg is 0, we take the global default.
297  */
298 template <class INDEXING_POLICY>
299 inline
300 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
301  (const ID_type& dataID,
302  CLID link_clid,
303  const index_type& elemID,
304  IProxyDict* sg)
305  : m_index (static_cast<stored_index_type>(elemID)),
306  m_element()
307 {
308  m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
309 }
310 
311 
312 /**
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.
318  *
319  * If @c sg is 0, we take the global default.
320  */
321 template <class INDEXING_POLICY>
322 inline
323 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
324  (sgkey_t key,
325  CLID link_clid,
326  const index_type& elemID,
327  IProxyDict* sg)
328  : m_key (key),
329  m_index (static_cast<stored_index_type>(elemID)),
330  m_element()
331 {
332  m_proxy.toIdentifiedObject (key, link_clid, sg);
333 }
334 
335 
336 /**
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.
343  *
344  * USE CAREFULLY: no coherency checks, we just trust you!
345  *
346  * If @c sg is 0, we take the global default.
347  */
348 template <class INDEXING_POLICY>
349 inline
350 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
351  (const ID_type& dataID,
352  CLID link_clid,
353  const index_type& elemID,
354  const ElementType& elt,
355  IProxyDict* sg)
356  : m_index (static_cast<stored_index_type>(elemID)),
357  m_element (elt)
358 {
359  m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
360 }
361 
362 
363 /**
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.
370  *
371  * USE CAREFULLY: no coherency checks, we just trust you!
372  *
373  * If @c sg is 0, we take the global default.
374  */
375 template <class INDEXING_POLICY>
376 inline
377 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
378  (sgkey_t key,
379  CLID link_clid,
380  const index_type& elemID,
381  const ElementType& elt,
382  IProxyDict* sg)
383  : m_key (key),
384  m_index (static_cast<stored_index_type>(elemID)),
385  m_element (elt)
386 {
387  m_proxy.toIdentifiedObject (key, link_clid, sg);
388 }
389 
390 
391 /**
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.
397  *
398  * If @c sg is 0, we take the global default.
399  */
400 template <class INDEXING_POLICY>
401 inline
402 GenericElementLinkBase<INDEXING_POLICY>::GenericElementLinkBase
403  (const_pointer_t obj,
404  CLID link_clid,
405  const index_type& elemID,
406  IProxyDict* sg)
407  : m_index (static_cast<stored_index_type>(elemID)),
408  m_element()
409 {
410  m_key = m_proxy.toStorableObject (obj, link_clid, sg);
411 }
412 
413 
414 /**
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.
418  *
419  * The index being constructed will reference the same container
420  * as @c other, but it will refer to element @c elemID.
421  */
422 template <class INDEXING_POLICY>
423 inline
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),
430  m_element()
431 {
432 }
433 
434 
435 /**
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.
439  */
440 template <class INDEXING_POLICY>
441 inline
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),
448  m_element()
449 {
450  if (dlink.isDefault()) {
451  INDEXING_POLICY::reset (m_index);
452  }
453 }
454 
455 
456 /**
457  * @brief Constructor from a link referencing a different type.
458  * @param other The object from which to copy.
459  *
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)
464  * are allowed.
465  */
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,
470  FROM_TRAITS*,
471  TO_TRAITS*)
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)
478 {
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.
481 }
482 
483 
484 /**
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).
494  */
495 template <class INDEXING_POLICY>
496 inline
497 void* GenericElementLinkBase<INDEXING_POLICY>::storableBase
498  (castfn_t* castfn, const CLID& clid, bool isConst) const
499 {
500  return m_proxy.storableBase (castfn, clid, isConst);
501 }
502 
503 
504 /**
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.
511  *
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.
516  *
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
519  * default.
520  */
521 template <class INDEXING_POLICY>
522 inline
523 bool GenericElementLinkBase<INDEXING_POLICY>::setStorableObject
524  (const_pointer_t data,
525  CLID link_clid,
526  bool replace,
527  IProxyDict* sg)
528 {
529  if (!m_proxy.isDefault()) {
530  if (!replace) return false;
531  INDEXING_POLICY::reset (m_index);
532  }
533 
534  m_key = m_proxy.toStorableObject (data, link_clid, sg);
535  return true;
536 }
537 
538 
539 /**
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.
546  *
547  * If the link is already set, this will return false and leave the
548  * link unchanged.
549  *
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
552  * default.
553  */
554 template <class INDEXING_POLICY>
555 inline
556 bool GenericElementLinkBase<INDEXING_POLICY>::toIndexedElement
557  (const_pointer_t obj,
558  CLID link_clid,
559  const index_type& elemID,
560  IProxyDict* sg)
561 {
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);
565  m_element.reset();
566  return true;
567  }
568  return false;
569 }
570 
571 
572 /**
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.
578  *
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
581  * default.
582  */
583 template <class INDEXING_POLICY>
584 inline
585 void GenericElementLinkBase<INDEXING_POLICY>::resetWithKeyAndIndex
586  (const ID_type& dataID,
587  CLID link_clid,
588  const index_type& elemID,
589  IProxyDict* sg)
590 {
591  m_key = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
592  m_index = static_cast<stored_index_type>(elemID);
593  m_element.reset();
594 }
595 
596 
597 /**
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.
603  *
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
606  * default.
607  */
608 template <class INDEXING_POLICY>
609 inline
610 void GenericElementLinkBase<INDEXING_POLICY>::resetWithKeyAndIndex
611  (sgkey_t key,
612  CLID link_clid,
613  const index_type& elemID,
614  IProxyDict* sg)
615 {
616  m_key = key;
617  m_proxy.toIdentifiedObject (key, link_clid, sg);
618  m_index = static_cast<stored_index_type>(elemID);
619  m_element.reset();
620 }
621 
622 
623 /**
624  * @brief Set the index part of the link.
625  * @param index New index value.
626  */
627 template <class INDEXING_POLICY>
628 inline
629 void
630 GenericElementLinkBase<INDEXING_POLICY>::setIndex (const index_type& index)
631 {
632  m_index = static_cast<stored_index_type>(index);
633 }
634 
635 
636 /**
637  * @brief Return the stored representation of the link index.
638  */
639 template <class INDEXING_POLICY>
640 inline
641 const typename GenericElementLinkBase<INDEXING_POLICY>::stored_index_type&
642 GenericElementLinkBase<INDEXING_POLICY>::storedIndex() const
643 {
644  return m_index;
645 }
646 
647 
648 /**
649  * @brief Set the cached element stored in the link.
650  * @param elt New value for the cached element.
651  */
652 template <class INDEXING_POLICY>
653 inline
654 void
655 GenericElementLinkBase<INDEXING_POLICY>::setCachedElement (const ElementType& elt) const
656 {
657  m_element.set (elt);
658 }
659 
660 
661 /**
662  * @brief Set the cached element stored in the link.
663  * @param elt New value for the cached element.
664  */
665 template <class INDEXING_POLICY>
666 inline
667 void
668 GenericElementLinkBase<INDEXING_POLICY>::storeCachedElement (const ElementType& elt)
669 {
670  m_element.store (elt);
671 }
672 
673 
674 /**
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.
678  *
679  * @c elt is left unmodified if there is no cached element.
680  */
681 template <class INDEXING_POLICY>
682 inline
683 bool
684 GenericElementLinkBase<INDEXING_POLICY>::getCachedElement (ElementConstPointer& elt) const
685 {
686  if (m_element.isValid()) {
687  elt = m_element.ptr();
688  return true;
689  }
690  return false;
691 }
692 
693 
694 /**
695  * @brief Return the internal proxy holder object.
696  */
697 template <class INDEXING_POLICY>
698 inline
699 const SG::DataProxyHolder&
700 GenericElementLinkBase<INDEXING_POLICY>::proxyHolder() const
701 {
702  return m_proxy;
703 }
704 
705 
706 } // namespace SG