ATLAS Offline Software
Loading...
Searching...
No Matches
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
13namespace SG {
14
15
16/**
17 * @brief Test the index validity.
18 * @returns True if the index is not valid (in default state).
19 */
20template <class INDEXING_POLICY>
21inline
22bool
23GenericElementLinkBase<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 */
32template <class INDEXING_POLICY>
33inline
34bool
35GenericElementLinkBase<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 */
44template <class INDEXING_POLICY>
45inline
46bool
47GenericElementLinkBase<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 */
56template <class INDEXING_POLICY>
57inline
58typename GenericElementLinkBase<INDEXING_POLICY>::index_type
59GenericElementLinkBase<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 */
70template <class INDEXING_POLICY>
71inline
72const typename GenericElementLinkBase<INDEXING_POLICY>::ID_type&
73GenericElementLinkBase<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 */
84template <class INDEXING_POLICY>
85inline
86typename GenericElementLinkBase<INDEXING_POLICY>::sgkey_t
87GenericElementLinkBase<INDEXING_POLICY>::key() const
88{
89 return m_key;
90}
91
92
93/**
94 * @brief Return the data source for this reference.
95 */
96template <class INDEXING_POLICY>
97inline
98IProxyDict*
99GenericElementLinkBase<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 */
114template <class INDEXING_POLICY>
115inline
116const SG::DataProxy*
117GenericElementLinkBase<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 */
126template <class INDEXING_POLICY>
127inline
128void 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 */
147template <class INDEXING_POLICY>
148inline
149bool
150GenericElementLinkBase<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 */
170template <class INDEXING_POLICY>
171inline
172bool
173GenericElementLinkBase<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 */
191template <class INDEXING_POLICY>
192inline
193bool 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 */
209template <class INDEXING_POLICY>
210inline
211bool 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 */
231template <class INDEXING_POLICY>
232template <class INDEX>
233requires (std::convertible_to<INDEX, size_t> &&
234 std::convertible_to<size_t, INDEX>)
235inline
236bool 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 */
263template <class INDEXING_POLICY>
264template <class INDEX>
265requires (!(std::convertible_to<INDEX, size_t> &&
266 std::convertible_to<size_t, INDEX>))
267inline
268bool 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 */
279template <class INDEXING_POLICY>
280inline
281GenericElementLinkBase<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 */
298template <class INDEXING_POLICY>
299inline
300GenericElementLinkBase<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 */
321template <class INDEXING_POLICY>
322inline
323GenericElementLinkBase<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 */
348template <class INDEXING_POLICY>
349inline
350GenericElementLinkBase<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 */
375template <class INDEXING_POLICY>
376inline
377GenericElementLinkBase<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 */
400template <class INDEXING_POLICY>
401inline
402GenericElementLinkBase<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 */
422template <class INDEXING_POLICY>
423inline
424GenericElementLinkBase<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 */
440template <class INDEXING_POLICY>
441inline
442GenericElementLinkBase<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 */
466template <class INDEXING_POLICY>
467template <class OTHER_INDEXING_POLICY, class FROM_TRAITS, class TO_TRAITS>
468GenericElementLinkBase<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 */
495template <class INDEXING_POLICY>
496inline
497void* 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 */
521template <class INDEXING_POLICY>
522inline
523bool 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 */
554template <class INDEXING_POLICY>
555inline
556bool 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 */
583template <class INDEXING_POLICY>
584inline
585void 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 */
608template <class INDEXING_POLICY>
609inline
610void 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 */
627template <class INDEXING_POLICY>
628inline
629void
630GenericElementLinkBase<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 */
639template <class INDEXING_POLICY>
640inline
641const typename GenericElementLinkBase<INDEXING_POLICY>::stored_index_type&
642GenericElementLinkBase<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 */
652template <class INDEXING_POLICY>
653inline
654void
655GenericElementLinkBase<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 */
665template <class INDEXING_POLICY>
666inline
667void
668GenericElementLinkBase<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 */
681template <class INDEXING_POLICY>
682inline
683bool
684GenericElementLinkBase<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 */
697template <class INDEXING_POLICY>
698inline
699const SG::DataProxyHolder&
700GenericElementLinkBase<INDEXING_POLICY>::proxyHolder() const
701{
702 return m_proxy;
703}
704
705
706} // namespace SG