ATLAS Offline Software
ElementLinkBase.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
5 */
6 /**
7  * @file AthLinks/ElementLinkBase.icc
8  * @author scott snyder <snyder@bnl.gov>
9  * @date Apr, 2014
10  * @brief Base class for ElementLinks to vectors of pointers.
11  */
12 
13 
14 /**
15  * @brief Test the index validity.
16  * @returns True if the index is not valid (in default state).
17  */
18 inline
19 bool ElementLinkBase::isDefaultIndex() const
20 {
21  return m_persIndex == INVALID;
22 }
23 
24 
25 /**
26  * @brief Test to see if this link has a cached element pointer.
27  */
28 inline
29 bool ElementLinkBase::hasCachedElement() const
30 {
31  return m_element.get() != 0;
32 }
33 
34 
35 /**
36  * @brief Test to see if this link is in the default state.
37  */
38 inline
39 bool ElementLinkBase::isDefault() const
40 {
41  return m_proxy.isDefault() && !hasCachedElement() && isDefaultIndex();
42 }
43 
44 
45 /**
46  * @brief Return the index of the link.
47  */
48 inline
49 ElementLinkBase::index_type
50 ElementLinkBase::index() const
51 {
52  if (m_persIndex == INVALID)
53  return static_cast<ElementLinkBase::index_type>(-1);
54  return m_persIndex;
55 }
56 
57 /**
58  * @brief Return the index of the link.
59  * (Deprecated; use @c index() instead.)
60  */
61 inline
62 ElementLinkBase::stored_index_type
63 ElementLinkBase::persIndex() const
64 {
65  return m_persIndex;
66 }
67 
68 
69 /**
70  * @brief Return the SG key that we reference, as a string.
71  *
72  * Returns a null string on failure.
73  */
74 inline
75 const ElementLinkBase::ID_type&
76 ElementLinkBase::dataID() const
77 {
78  return m_proxy.dataID();
79 }
80 
81 
82 /**
83  * @brief Return the SG key that we reference, as a hash.
84  *
85  * Returns 0 on failure.
86  */
87 inline
88 ElementLinkBase::sgkey_t
89 ElementLinkBase::key() const
90 {
91  return m_persKey;
92 }
93 
94 /**
95  * @brief Return the SG key that we reference, as a hash.
96  * (Deprecated; use @c key instead.)
97  *
98  * Returns 0 on failure.
99  */
100 inline
101 ElementLinkBase::sgkey_t
102 ElementLinkBase::persKey() const
103 {
104  return m_persKey;
105 }
106 
107 
108 /**
109  * @brief Return the data source for this reference.
110  */
111 inline
112 IProxyDict* ElementLinkBase::source() const
113 {
114  return m_proxy.source();
115 }
116 
117 
118 /**
119  * @brief Return the SG proxy for the container holding this element.
120  *
121  * If this is a null link, we return 0.
122  * If we're directly referencing an object that's not in StoreGate,
123  * either return 0 or throw @c ExcPointerNotInSG, depending
124  * on @c nothrow. Otherwise, return the proxy for the object
125  * we're referencing.
126  */
127 inline
128 const SG::DataProxy* ElementLinkBase::proxy() const
129 {
130  return m_proxy.proxy(true);
131 }
132 
133 
134 /**
135  * @brief Reset the link to a null state.
136  */
137 inline
138 void ElementLinkBase::reset ()
139 {
140  m_proxy.clear();
141  m_persKey = 0;
142  clearCachedElement();
143  m_persIndex = INVALID;
144 }
145 
146 
147 /**
148  * @brief Finish initialization after link has been read.
149  * @param sg Associated store.
150  *
151  * This should be called after a link has been read by root
152  * in order to set the proxy pointer.
153  * Returns true.
154  *
155  * If @c sg is 0, then we use the global default store.
156  */
157 inline
158 bool ElementLinkBase::toTransient (IProxyDict* sg /*= 0*/)
159 {
160  m_proxy.toTransient (m_persKey, sg);
161  clearCachedElement();
162  return true;
163 }
164 
165 
166 /**
167  * @brief Prepare this link for writing.
168  *
169  * This method should be called before trying to write the link with root.
170  * It will make sure the persistent fields of the link are valid.
171  * It will also perform remapping if needed.
172  *
173  * Will return true on success. Will return false if either the container
174  * or the element index has not been specified. Will throw
175  * @c ExcPointerNotInSG if the link is referencing a container that
176  * is not in SG.
177  */
178 inline
179 bool ElementLinkBase::toPersistent()
180 {
181  if (isDefault()) return true;
182  if (m_proxy.isDefault() || isDefaultIndex()) return false;
183  if (m_proxy.toPersistent (m_persKey, m_persIndex))
184  clearCachedElement();
185  return true;
186 }
187 
188 
189 /**
190  * @brief Adjust for thinning.
191  *
192  * If this link points to a container that has been thinned,
193  * it will be adjusted accordingly.
194  *
195  * Returns @c true if the link was changed; @c false otherwise.
196  */
197 inline
198 bool ElementLinkBase::thin()
199 {
200  return thin (SG::getThinningCache());
201 }
202 
203 
204 /**
205  * @brief Adjust for thinning.
206  * @param thinningCache Thinning cache for the current stream
207  * (may be null).
208  *
209  * If this link points to a container that has been thinned,
210  * it will be adjusted accordingly.
211  *
212  * Returns @c true if the link was changed; @c false otherwise.
213  */
214 inline
215 bool ElementLinkBase::thin (const SG::ThinningCache* thinningCache)
216 {
217  bool ret1 = toPersistent();
218  size_t index = m_persIndex;
219  bool ret = m_proxy.thin (m_persKey, index, thinningCache);
220  if (ret)
221  m_persIndex = static_cast<stored_index_type>(index);
222  return ret1 || ret;
223 }
224 
225 
226 /**
227  * @brief Default constructor. Makes a null link.
228  */
229 inline
230 ElementLinkBase::ElementLinkBase()
231  : m_persKey (0),
232  m_persIndex (INVALID)
233 {
234 }
235 
236 
237 /**
238  * @brief Construct a link from a string key and an index.
239  * @param dataID Key of the object.
240  * @param link_clid CLID of the link being set.
241  * @param elemID The index of the element within the container.
242  * @param sg Associated store.
243  *
244  * If @c sg is 0, we take the global default.
245  */
246 inline
247 ElementLinkBase::ElementLinkBase (const ID_type& dataID,
248  CLID link_clid,
249  index_type elemID,
250  IProxyDict* sg)
251  : m_persIndex (static_cast<stored_index_type>(elemID))
252 {
253  m_persKey = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
254 }
255 
256 
257 /**
258  * @brief Construct a link from a hashed key and an index.
259  * @param key Hashed key of the object.
260  * @param link_clid CLID of the link being set.
261  * @param elemID The index of the element within the container.
262  * @param sg Associated store.
263  *
264  * If @c sg is 0, we take the global default.
265  */
266 inline
267 ElementLinkBase::ElementLinkBase (sgkey_t key,
268  CLID link_clid,
269  index_type elemID,
270  IProxyDict* sg)
271  : m_persKey (key),
272  m_persIndex (static_cast<stored_index_type>(elemID))
273 {
274  m_proxy.toIdentifiedObject (key, link_clid, sg);
275 }
276 
277 
278 /**
279  * @brief Construct a link from a string key, index, AND pointer to element.
280  * @param dataID Key of the object.
281  * @param link_clid CLID of the link being set.
282  * @param elemID The index of the element within the container.
283  * @param elt Pointer to the element.
284  * @param sg Associated store.
285  *
286  * USE CAREFULLY: no coherency checks, we just trust you!
287  *
288  * If @c sg is 0, we take the global default.
289  */
290 inline
291 ElementLinkBase::ElementLinkBase (const ID_type& dataID,
292  CLID link_clid,
293  index_type elemID,
294  const void* elt,
295  IProxyDict* sg)
296  : m_persIndex (static_cast<stored_index_type>(elemID)),
297  m_element (elt)
298 {
299  m_persKey = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
300 }
301 
302 
303 /**
304  * @brief Construct a link from a hashed key, index, AND pointer to element.
305  * @param key Hashed key of the object.
306  * @param link_clid CLID of the link being set.
307  * @param elemID The index of the element within the container.
308  * @param elt Pointer to the element.
309  * @param sg Associated store.
310  *
311  * USE CAREFULLY: no coherency checks, we just trust you!
312  *
313  * If @c sg is 0, we take the global default.
314  */
315 inline
316 ElementLinkBase::ElementLinkBase (sgkey_t key,
317  CLID link_clid,
318  index_type elemID,
319  const void* elt,
320  IProxyDict* sg)
321  : m_persKey (key),
322  m_persIndex (static_cast<stored_index_type>(elemID)),
323  m_element (elt)
324 {
325  m_proxy.toIdentifiedObject (key, link_clid, sg);
326 }
327 
328 
329 /**
330  * @brief Construct a link from an index and pointer to the container.
331  * @param obj Pointer to the container (storable).
332  * @param link_clid CLID of the link being set.
333  * @param elemID The index of the element within the container.
334  * @param sg Associated store.
335  *
336  * If @c sg is 0, we take the global default.
337  */
338 inline
339 ElementLinkBase::ElementLinkBase (const_pointer_t obj,
340  CLID link_clid,
341  index_type elemID,
342  IProxyDict* sg)
343  : m_persIndex (static_cast<stored_index_type>(elemID))
344 {
345  m_persKey = m_proxy.toStorableObject (obj, link_clid, sg);
346 }
347 
348 
349 /**
350  * @brief Construct a link from another link, changing the index.
351  * @param other The source link.
352  * @param elemID The index for the new link.
353  *
354  * The index being constructed will reference the same container
355  * as @c other, but it will refer to element @c elemID.
356  */
357 inline
358 ElementLinkBase::ElementLinkBase (const ElementLinkBase& other,
359  index_type elemID)
360  : m_persKey (other.m_persKey),
361  m_persIndex (static_cast<stored_index_type>(elemID)),
362  m_proxy (other.m_proxy)
363 {
364 }
365 
366 
367 /**
368  * @brief Construct a link from a DataLink and an index.
369  * @param dlink Link to the container.
370  * @param index The index of the element within the container.
371  */
372 inline
373 ElementLinkBase::ElementLinkBase (const DataLinkBase& dlink,
374  index_type index)
375  : m_persKey (dlink.key()),
376  m_persIndex (dlink.isDefault() ? INVALID : static_cast<stored_index_type>(index)),
377  m_proxy (dlink.m_proxy)
378 {
379 }
380 
381 
382 /**
383  * @brief Constructor from a link referencing a different type.
384  * @param other The object from which to copy.
385  *
386  * @c FROM_TRAITS is the @c ElementLinkTraits class for @c other;
387  * @c TO_TRAITS is the traits class for this object.
388  * The actual pointer values are not used, just the types are used.
389  * Default conversions for the storable pointer (i.e., derived->base)
390  * are allowed.
391  */
392 template <class FROM_TRAITS, class TO_TRAITS>
393 ElementLinkBase::ElementLinkBase (const ElementLinkBase& other,
394  FROM_TRAITS*,
395  TO_TRAITS*)
396  : m_persKey (other.m_persKey),
397  m_persIndex (other.m_persIndex),
398  m_proxy (other.m_proxy,
399  (typename FROM_TRAITS::Storable*)0,
400  (typename TO_TRAITS::Storable*)0)
401 {
402  typedef typename FROM_TRAITS::IndexingPolicy FromIndexingPolicy;
403  typedef typename TO_TRAITS::IndexingPolicy ToIndexingPolicy;
404  typedef typename FromIndexingPolicy::ElementType FromElementType;
405  typedef typename ToIndexingPolicy::ElementType ToElementType;
406  FromElementType from_elt = reinterpret_cast<FromElementType>(other.m_element.get());
407  ToElementType to_elt = from_elt;
408  storeCachedElement (to_elt);
409 }
410 
411 
412 /**
413  * @brief Return a pointer to the currently-referenced container object.
414  * @param castfn Function to do the cast from data proxy to object.
415  * If 0, use a dynamic cast.
416  * @param clid The CLID of the desired object.
417  * This is used to determine how the returned pointer
418  * is to be converted.
419  * @param isConst True if the returned object will be treated as const.
420  * @return A pointer to an object of the type given by @a clid,
421  * or null on a failure (or if the reference is null).
422  */
423 inline
424 void* ElementLinkBase::storableBase (castfn_t* castfn,
425  CLID clid,
426  bool isConst) const
427 {
428  return m_proxy.storableBase (castfn, clid, isConst);
429 }
430 
431 
432 /**
433  * @brief Set the container referenced by the link to @c data.
434  * @param data Pointer to the new container.
435  * @param link_clid CLID of the link being set.
436  * @param replace True if we can change an existing link.
437  * @param sg Associated store.
438  * @returns True if the link was changed.
439  *
440  * If the link is already set, this will return false and leave the
441  * link unchanged unless @c replace is set. The @c replace argument
442  * should be set if the element is now in a new storable container;
443  * e.g. element ptr has been put in a new view container.
444  *
445  * If @c sg is 0, then we take the store from whatever the link's currently
446  * set to. If the link has no current store, then we take the global
447  * default.
448  */
449 inline
450 bool ElementLinkBase::setStorableObject (const_pointer_t data,
451  CLID link_clid,
452  bool replace,
453  IProxyDict* sg)
454 {
455  if (!m_proxy.isDefault()) {
456  if (!replace) return false;
457  m_persIndex = INVALID;
458  }
459 
460  m_persKey = m_proxy.toStorableObject (data, link_clid, sg);
461  return true;
462 }
463 
464 
465 /**
466  * @brief Set the link to an element given by index and pointer to container.
467  * @param obj Pointer to the container (storable).
468  * @param link_clid CLID of the link being set.
469  * @param elemID The index of the element within the container.
470  * @param sg Associated store.
471  * @returns True if the link was changed.
472  *
473  * If the link is already set, this will return false and leave the
474  * link unchanged.
475  *
476  * If @c sg is 0, then we take the store from whatever the link's currently
477  * set to. If the link has no current store, then we take the global
478  * default.
479  */
480 inline
481 bool ElementLinkBase::toIndexedElement (const_pointer_t obj,
482  CLID link_clid,
483  index_type elemID,
484  IProxyDict* sg)
485 {
486  if (m_proxy.isDefault() && isDefaultIndex() && !hasCachedElement()) {
487  m_persKey = m_proxy.toStorableObject (obj, link_clid, sg);
488  m_persIndex = static_cast<stored_index_type>(elemID);
489  //clearCachedElement(); // Redundant --- must be 0 due to above test.
490  return true;
491  }
492  return false;
493 }
494 
495 
496 /**
497  * @brief Set the link to an element given by string key and index.
498  * @param dataID Key of the object.
499  * @param link_clid CLID of the link being set.
500  * @param elemID The index of the element within the container.
501  * @param sg Associated store.
502  *
503  * If @c sg is 0, then we take the store from whatever the link's currently
504  * set to. If the link has no current store, then we take the global
505  * default.
506  */
507 inline
508 void ElementLinkBase::resetWithKeyAndIndex (const ID_type& dataID,
509  CLID link_clid,
510  index_type elemID,
511  IProxyDict* sg)
512 {
513  m_persKey = m_proxy.toIdentifiedObject (dataID, link_clid, sg);
514  m_persIndex = static_cast<stored_index_type>(elemID);
515  clearCachedElement();
516 }
517 
518 
519 /**
520  * @brief Set the link to an element given by string key and index.
521  * @param key Hashed key of the object.
522  * @param link_clid CLID of the link being set.
523  * @param elemID The index of the element within the container.
524  * @param sg Associated store.
525  *
526  * If @c sg is 0, then we take the store from whatever the link's currently
527  * set to. If the link has no current store, then we take the global
528  * default.
529  */
530 inline
531 void ElementLinkBase::resetWithKeyAndIndex (sgkey_t key,
532  CLID link_clid,
533  index_type elemID,
534  IProxyDict* sg)
535 {
536  m_persKey = key;
537  m_proxy.toIdentifiedObject (key, link_clid, sg);
538  m_persIndex = static_cast<stored_index_type>(elemID);
539  clearCachedElement();
540 }
541 
542 
543 /**
544  * @brief Set the index part of the link.
545  * @param index New index value.
546  */
547 inline
548 void ElementLinkBase::setIndex (index_type index)
549 {
550  m_persIndex = static_cast<stored_index_type>(index);
551 }
552 
553 
554 /**
555  * @brief Return the stored representation of the link index.
556  */
557 inline
558 const ElementLinkBase::stored_index_type&
559 ElementLinkBase::storedIndex() const
560 {
561  return m_persIndex;
562 }
563 
564 
565 /**
566  * @brief Clear the currently-cached element.
567  */
568 inline
569 void ElementLinkBase::clearCachedElement()
570 {
571  storeCachedElement (nullptr);
572 }
573 
574 
575 /**
576  * @brief Set the cached element stored in the link,
577  * assuming the cached element is null.
578  * @param elt New value for the cached element.
579  */
580 inline
581 void ElementLinkBase::setCachedElement (ElementType elt) const
582 {
583  m_element.set (elt);
584 }
585 
586 
587 /**
588  * @brief Set the cached element stored in the link.
589  * @param elt New value for the cached element.
590  */
591 inline
592 void ElementLinkBase::storeCachedElement (ElementType elt)
593 {
594  m_element.store (elt);
595 }
596 
597 
598 /**
599  * @brief Retrieve the cached element from the link.
600  * @param elt[out] The cached element.
601  * @returns True if an element was cached; false otherwise.
602  *
603  * @c elt is left unmodified if there is no cached element.
604  */
605 template <class T>
606 inline
607 bool ElementLinkBase::getCachedElement (const T* & elt) const
608 {
609  if (m_element.get()) {
610  elt = reinterpret_cast<const T*> (m_element.ptr());
611  return true;
612  }
613  return false;
614 }
615 
616 
617 /**
618  * @brief Return the internal proxy holder object.
619  */
620 inline
621 const SG::DataProxyHolder& ElementLinkBase::proxyHolder() const
622 {
623  return m_proxy;
624 }
625 
626