1// Dear emacs, this is -*- c++ -*-
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5#ifndef ATHLINKS_DATALINK_ICC
6#define ATHLINKS_DATALINK_ICC
15#include "xAODRootAccessInterfaces/TVirtualEvent.h"
16#include "xAODRootAccessInterfaces/TActiveEvent.h"
18////////////////////////////////////////////////////////////////////////////////
20// Implementation of the different constructors
23/// This constructor creates an object that will either return a null pointer
24/// when asked for one, or throw an exception when trying to de-reference it.
26template< typename STORABLE >
27DataLink< STORABLE >::DataLink()
28 : DataLinkBase(), m_object( 0 ), m_event( xAOD::TActiveEvent::event() ) {
32/// This constructor allows the user to create a null-pointer that uses an
33/// alternative TVirtualEvent object as its store.
35/// @param event Pointer to an alternative TVirtualEvent object
37template< typename STORABLE >
38DataLink< STORABLE >::DataLink( xAOD::TVirtualEvent* event )
39 : DataLinkBase(), m_object( 0 ), m_event( event ) {
43/// This constructor can be used to create a valid object based on a reference
44/// to an existing object, that's already part of the current event. In case
45/// the object can not be found in the current event, the constructor throws
48/// @param data A constant reference to the object that the smart pointer
50/// @param event Pointer to an alternative TVirtualEvent object
52template< typename STORABLE >
53DataLink< STORABLE >::DataLink( const_reference data,
54 xAOD::TVirtualEvent* event )
55 : DataLinkBase(), m_object( &data ), m_event( event ) {
57 // Get the active event if the user didn't specify one explicitly:
59 m_event = xAOD::TActiveEvent::event();
62 // Find the identifier of the object that we received:
66/// This constructor can be used to create a valid object based on a pointer
67/// to an existing object, that's already part of the current event. In case
68/// the object can not be found in the current event, the constructor throws
71/// @param data A constant pointer to the object that the smart pointer
73/// @param event Pointer to an alternative TVirtualEvent object
75template< typename STORABLE >
76DataLink< STORABLE >::DataLink( const_pointer data, xAOD::TVirtualEvent* event )
77 : DataLinkBase(), m_object( data ), m_event( event ) {
79 // Get the active event if the user didn't specify one explicitly:
81 m_event = xAOD::TActiveEvent::event();
84 // Find the identifier of the object that we received:
88/// This constructor can be used to create a valid object based on a pointer
89/// to an existing object, that's already part of the current event. In case
90/// the object can not be found in the current event, the constructor throws
92/// It also takes a dummy @c EventContext argument, to avoid the need
93/// for downstream #ifdefs.
95/// @param data A constant pointer to the object that the smart pointer
98template< typename STORABLE >
99DataLink< STORABLE >::DataLink( const_pointer data, const EventContext& )
105/// This is probably the most convenient version of the constructors.
106/// It receives a string identifier (branch name) for the object that the smart
107/// pointer should reference.
109/// @param id A string identifier for the object to be referenced
110/// @param event Pointer to an alternative TVirtualEvent object
112template< typename STORABLE >
113DataLink< STORABLE >::DataLink( const ID_type& id, xAOD::TVirtualEvent* event )
114 : DataLinkBase(), m_object( 0 ), m_event( event ) {
116 // Get the active event if the user didn't specify one explicitly:
118 m_event = xAOD::TActiveEvent::event();
121 // Translate the id into a hashed key:
122 m_persKey = m_event->getHash( id );
125/// This is the most cost-effective of the constructors after the default
126/// one. It relies on the user knowing exactly what hashed key to ask for
127/// for the target object.
129/// @param key A hashed key identifying the object to be referenced
130/// @param event Pointer to an alternative TVirtualEvent object
132template< typename STORABLE >
133DataLink< STORABLE >::DataLink( sgkey_t key, xAOD::TVirtualEvent* event )
134 : DataLinkBase( key ), m_object( 0 ), m_event( event ) {
136 // Get the active event if the user didn't specify one explicitly:
138 m_event = xAOD::TActiveEvent::event();
142/// Simple copy-constructor. It just copies the persistent information
143/// from the base class together with the TVirtualEvent pointer that the parent
146/// @param parent The parent object to be copied
148template< typename STORABLE >
149template< typename T >
150DataLink< STORABLE >::DataLink( const DataLink< T >& parent )
151 : DataLinkBase( parent ), m_object( 0 ), m_event( parent.m_event ) {
156////////////////////////////////////////////////////////////////////////////////
158////////////////////////////////////////////////////////////////////////////////
160// Implementation of the different setter functions
163/// This function should be used to set up the object when your code has a
164/// reference to the target object.
166/// The function will throw an exception if the supplied object can't be found
167/// in the current event.
169/// @param data A reference to the target object
171template< typename STORABLE >
172void DataLink< STORABLE >::toStorableObject( const_reference data ) {
174 // Remember the pointer:
177 // Now try to look up the object in the store:
183/// This function sets up the object to point at the default object of the
184/// template type in the event. It can be useful when only one object of a
185/// given type is available.
187template< typename STORABLE >
188void DataLink< STORABLE >::toDefaultObject() {
190 // Reset the cached pointer:
193 // Set a special value for the persistent variable:
194 setPersKey( xAOD::TVirtualEvent::DEFAULT_KEY );
199/// This is one of the more convenient functions. It sets up the smart pointer
200/// using a user-readable string idetifier for the target object.
202/// @param id A string identifier (branch name) for the target object
204template< typename STORABLE >
205void DataLink< STORABLE >::toIdentifiedObject( const ID_type& id ) {
207 // Check if we have a valid event:
209 throw std::runtime_error( "DataLink::toIdentifiedObject: No valid "
210 "TVirtualEvent pointer available (key: " +
214 // Reset the cached pointer:
217 // Set the persistent key using this identifier:
218 m_persKey = m_event->getHash( id );
223/// This function hardly has to do anything. It just sets the received key as
224/// the persistent information for the object, and resets its internals.
226/// @param key The hashed key for the target object
228template< typename STORABLE >
229void DataLink< STORABLE >::toIdentifiedObject( sgkey_t key ) {
231 // Reset the cached pointer:
234 // Set the persistent key:
241////////////////////////////////////////////////////////////////////////////////
243////////////////////////////////////////////////////////////////////////////////
245// Implementation of the different accessor functions
248/// This operator can be used to get a constant reference to the object.
249/// In most cases though one should probably use the -> operator instead.
250/// The code throws an exception if the target object is not available.
252/// @returns A constant reference to the target object if available
254template< class STORABLE >
255typename DataLink< STORABLE >::const_reference
256DataLink< STORABLE >::operator*() const {
258 // See if we have a valid object:
259 const_pointer ptr = cptr();
261 // If not, throw an exception:
263 throw std::runtime_error( "DataLink::operator*: No valid target for the "
267 // Return the reference. Notice that we're not using the temporary variable
272/// This function is doing most of the heavy lifting. It interacts with the
273/// TVirtualEvent object to deliver a pointer to the target object to the user.
275/// @returns A constant pointer to the target object if available, a
276/// null pointer if not
278template< class STORABLE >
279typename DataLink< STORABLE >::const_pointer
280DataLink< STORABLE >::cptr() const {
282 // If the object is already cached, return right away:
283 if( m_object || ( ! m_event ) ) return m_object;
285 /// Default key, calculated just once:
286 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
287 xAOD::TVirtualEvent::KEY_MASK );
289 // If the key is nonsensical, fail silently:
290 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
294 // Ask the event object for the object in question:
295 if( ! m_event->retrieve( m_object, m_persKey ) ) {
299 // Return what we acquired:
303template< class STORABLE >
304bool DataLink< STORABLE >::isValid() const {
306 // If we have an object already cached, the answer is easy:
311 // If there's no event object, we won't be able to retrieve anything:
316 /// Default key, calculated just once:
317 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
318 xAOD::TVirtualEvent::KEY_MASK );
320 // Check for non-valid keys:
321 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
325 // Try retrieving the object:
326 if( ! m_event->retrieve( m_object, m_persKey, true ) ) {
330 // Apparently the link can be de-referenced:
334template< typename STORABLE >
335const typename DataLink< STORABLE >::ID_type&
336DataLink< STORABLE >::dataID() const {
338 return m_event->getName( persKey() );
342////////////////////////////////////////////////////////////////////////////////
344/// This function is just here to enable us compiling the same EDM code as
345/// we do offline. We don't actually need to prepare this object for being
346/// written out, it's always in a consistent state.
348/// @returns A dummy value. Just to have the same signature as the offline
351template< class STORABLE >
352bool DataLink< STORABLE >::toPersistent() {
357/// This function just resets the cached pointer when ROOT streams in a new
358/// object from a TBranch.
360/// @returns A dummy value. Just to have the same signature as the offline
363template< class STORABLE >
364bool DataLink< STORABLE >::toTransient() {
370/// This function is used internally to find the hashed identifier for an object
371/// that was given to the DataLink either by reference or pointer. It throws an
372/// exception if the object can't be found in the event.
374template< class STORABLE >
375void DataLink< STORABLE >::findIdentifier() {
377 // Allow tests to create a link object, even without setting up an event
379 if (m_event == nullptr) {
380 Warning("DataLink::findIdentifier", "Event object is not available");
384 // Ask the event for the identifier of this object:
385 const sgkey_t key = m_event->getKey( m_object );
387 Warning( "DataLink::findIdentifier",
388 "Couldn't find the received object in the current event" );
391 // Remember this key:
397#endif // ATHLINKS_DATALINK_ICC