ATLAS Offline Software
Loading...
Searching...
No Matches
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 */
18inline
19bool 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 */
28inline
29bool 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 */
38inline
39bool ElementLinkBase::isDefault() const
40{
41 return m_proxy.isDefault() && !hasCachedElement() && isDefaultIndex();
42}
43
44
45/**
46 * @brief Return the index of the link.
47 */
48inline
49ElementLinkBase::index_type
50ElementLinkBase::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 */
61inline
62ElementLinkBase::stored_index_type
63ElementLinkBase::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 */
74inline
75const ElementLinkBase::ID_type&
76ElementLinkBase::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 */
87inline
88ElementLinkBase::sgkey_t
89ElementLinkBase::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 */
100inline
101ElementLinkBase::sgkey_t
102ElementLinkBase::persKey() const
103{
104 return m_persKey;
105}
106
107
108/**
109 * @brief Return the data source for this reference.
110 */
111inline
112IProxyDict* 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 */
127inline
128const 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 */
137inline
138void 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 */
157inline
158bool 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 */
178inline
179bool 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 */
197inline
198bool 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 */
214inline
215bool 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 */
229inline
230ElementLinkBase::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 */
246inline
247ElementLinkBase::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 */
266inline
267ElementLinkBase::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 */
290inline
291ElementLinkBase::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 */
315inline
316ElementLinkBase::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 */
338inline
339ElementLinkBase::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 */
357inline
358ElementLinkBase::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 */
372inline
373ElementLinkBase::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 */
392template <class FROM_TRAITS, class TO_TRAITS>
393ElementLinkBase::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 */
423inline
424void* 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 */
449inline
450bool 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 */
480inline
481bool 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 */
507inline
508void 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 */
530inline
531void 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 */
547inline
548void 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 */
557inline
558const ElementLinkBase::stored_index_type&
559ElementLinkBase::storedIndex() const
560{
561 return m_persIndex;
562}
563
564
565/**
566 * @brief Clear the currently-cached element.
567 */
568inline
569void 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 */
580inline
581void 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 */
591inline
592void 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 */
605template <class T>
606inline
607bool 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 */
620inline
621const SG::DataProxyHolder& ElementLinkBase::proxyHolder() const
622{
623 return m_proxy;
624}
625
626