ATLAS Offline Software
Loading...
Searching...
No Matches
A/AthLinks/DataLink.icc
Go to the documentation of this file.
1// Dear emacs, this is -*- c++ -*-
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4 */
5#ifndef ATHLINKS_DATALINK_ICC
6#define ATHLINKS_DATALINK_ICC
7
8// System include(s):
9#include <stdexcept>
10
11// ROOT include(s):
12#include <TError.h>
13
14// EDM include(s):
15#include "xAODRootAccessInterfaces/TVirtualEvent.h"
16#include "xAODRootAccessInterfaces/TActiveEvent.h"
17
18////////////////////////////////////////////////////////////////////////////////
19//
20// Implementation of the different constructors
21//
22
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.
25///
26template< typename STORABLE >
27DataLink< STORABLE >::DataLink()
28 : DataLinkBase(), m_object( 0 ), m_event( xAOD::TActiveEvent::event() ) {
29
30}
31
32/// This constructor allows the user to create a null-pointer that uses an
33/// alternative TVirtualEvent object as its store.
34///
35/// @param event Pointer to an alternative TVirtualEvent object
36///
37template< typename STORABLE >
38DataLink< STORABLE >::DataLink( xAOD::TVirtualEvent* event )
39 : DataLinkBase(), m_object( 0 ), m_event( event ) {
40
41}
42
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
46/// an exception.
47///
48/// @param data A constant reference to the object that the smart pointer
49/// should point to
50/// @param event Pointer to an alternative TVirtualEvent object
51///
52template< typename STORABLE >
53DataLink< STORABLE >::DataLink( const_reference data,
54 xAOD::TVirtualEvent* event )
55 : DataLinkBase(), m_object( &data ), m_event( event ) {
56
57 // Get the active event if the user didn't specify one explicitly:
58 if( ! m_event ) {
59 m_event = xAOD::TActiveEvent::event();
60 }
61
62 // Find the identifier of the object that we received:
63 findIdentifier();
64}
65
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
69/// an exception.
70///
71/// @param data A constant pointer to the object that the smart pointer
72/// should point to
73/// @param event Pointer to an alternative TVirtualEvent object
74///
75template< typename STORABLE >
76DataLink< STORABLE >::DataLink( const_pointer data, xAOD::TVirtualEvent* event )
77 : DataLinkBase(), m_object( data ), m_event( event ) {
78
79 // Get the active event if the user didn't specify one explicitly:
80 if( ! m_event ) {
81 m_event = xAOD::TActiveEvent::event();
82 }
83
84 // Find the identifier of the object that we received:
85 findIdentifier();
86}
87
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
91/// an exception.
92/// It also takes a dummy @c EventContext argument, to avoid the need
93/// for downstream #ifdefs.
94///
95/// @param data A constant pointer to the object that the smart pointer
96/// should point to
97///
98template< typename STORABLE >
99DataLink< STORABLE >::DataLink( const_pointer data, const EventContext& )
100 : DataLink( data )
101{
102}
103
104
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.
108///
109/// @param id A string identifier for the object to be referenced
110/// @param event Pointer to an alternative TVirtualEvent object
111///
112template< typename STORABLE >
113DataLink< STORABLE >::DataLink( const ID_type& id, xAOD::TVirtualEvent* event )
114 : DataLinkBase(), m_object( 0 ), m_event( event ) {
115
116 // Get the active event if the user didn't specify one explicitly:
117 if( ! m_event ) {
118 m_event = xAOD::TActiveEvent::event();
119 }
120
121 // Translate the id into a hashed key:
122 m_persKey = m_event->getHash( id );
123}
124
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.
128///
129/// @param key A hashed key identifying the object to be referenced
130/// @param event Pointer to an alternative TVirtualEvent object
131///
132template< typename STORABLE >
133DataLink< STORABLE >::DataLink( sgkey_t key, xAOD::TVirtualEvent* event )
134 : DataLinkBase( key ), m_object( 0 ), m_event( event ) {
135
136 // Get the active event if the user didn't specify one explicitly:
137 if( ! m_event ) {
138 m_event = xAOD::TActiveEvent::event();
139 }
140}
141
142/// Simple copy-constructor. It just copies the persistent information
143/// from the base class together with the TVirtualEvent pointer that the parent
144/// class had.
145///
146/// @param parent The parent object to be copied
147///
148template< typename STORABLE >
149template< typename T >
150DataLink< STORABLE >::DataLink( const DataLink< T >& parent )
151 : DataLinkBase( parent ), m_object( 0 ), m_event( parent.m_event ) {
152
153}
154
155//
156////////////////////////////////////////////////////////////////////////////////
157
158////////////////////////////////////////////////////////////////////////////////
159//
160// Implementation of the different setter functions
161//
162
163/// This function should be used to set up the object when your code has a
164/// reference to the target object.
165///
166/// The function will throw an exception if the supplied object can't be found
167/// in the current event.
168///
169/// @param data A reference to the target object
170///
171template< typename STORABLE >
172void DataLink< STORABLE >::toStorableObject( const_reference data ) {
173
174 // Remember the pointer:
175 m_object = &data;
176
177 // Now try to look up the object in the store:
178 findIdentifier();
179
180 return;
181}
182
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.
186///
187template< typename STORABLE >
188void DataLink< STORABLE >::toDefaultObject() {
189
190 // Reset the cached pointer:
191 m_object = 0;
192
193 // Set a special value for the persistent variable:
194 setPersKey( xAOD::TVirtualEvent::DEFAULT_KEY );
195
196 return;
197}
198
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.
201///
202/// @param id A string identifier (branch name) for the target object
203///
204template< typename STORABLE >
205void DataLink< STORABLE >::toIdentifiedObject( const ID_type& id ) {
206
207 // Check if we have a valid event:
208 if( ! m_event ) {
209 throw std::runtime_error( "DataLink::toIdentifiedObject: No valid "
210 "TVirtualEvent pointer available (key: " +
211 id + ")" );
212 }
213
214 // Reset the cached pointer:
215 m_object = 0;
216
217 // Set the persistent key using this identifier:
218 m_persKey = m_event->getHash( id );
219
220 return;
221}
222
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.
225///
226/// @param key The hashed key for the target object
227///
228template< typename STORABLE >
229void DataLink< STORABLE >::toIdentifiedObject( sgkey_t key ) {
230
231 // Reset the cached pointer:
232 m_object = 0;
233
234 // Set the persistent key:
235 m_persKey = key;
236
237 return;
238}
239
240//
241////////////////////////////////////////////////////////////////////////////////
242
243////////////////////////////////////////////////////////////////////////////////
244//
245// Implementation of the different accessor functions
246//
247
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.
251///
252/// @returns A constant reference to the target object if available
253///
254template< class STORABLE >
255typename DataLink< STORABLE >::const_reference
256DataLink< STORABLE >::operator*() const {
257
258 // See if we have a valid object:
259 const_pointer ptr = cptr();
260
261 // If not, throw an exception:
262 if( ! ptr ) {
263 throw std::runtime_error( "DataLink::operator*: No valid target for the "
264 "object" );
265 }
266
267 // Return the reference. Notice that we're not using the temporary variable
268 // here...
269 return *m_object;
270}
271
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.
274///
275/// @returns A constant pointer to the target object if available, a
276/// null pointer if not
277///
278template< class STORABLE >
279typename DataLink< STORABLE >::const_pointer
280DataLink< STORABLE >::cptr() const {
281
282 // If the object is already cached, return right away:
283 if( m_object || ( ! m_event ) ) return m_object;
284
285 /// Default key, calculated just once:
286 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
287 xAOD::TVirtualEvent::KEY_MASK );
288
289 // If the key is nonsensical, fail silently:
290 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
291 return 0;
292 }
293
294 // Ask the event object for the object in question:
295 if( ! m_event->retrieve( m_object, m_persKey ) ) {
296 m_object = 0;
297 }
298
299 // Return what we acquired:
300 return m_object;
301}
302
303template< class STORABLE >
304bool DataLink< STORABLE >::isValid() const {
305
306 // If we have an object already cached, the answer is easy:
307 if( m_object ) {
308 return true;
309 }
310
311 // If there's no event object, we won't be able to retrieve anything:
312 if( ! m_event ) {
313 return false;
314 }
315
316 /// Default key, calculated just once:
317 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
318 xAOD::TVirtualEvent::KEY_MASK );
319
320 // Check for non-valid keys:
321 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
322 return false;
323 }
324
325 // Try retrieving the object:
326 if( ! m_event->retrieve( m_object, m_persKey, true ) ) {
327 return false;
328 }
329
330 // Apparently the link can be de-referenced:
331 return true;
332}
333
334template< typename STORABLE >
335const typename DataLink< STORABLE >::ID_type&
336DataLink< STORABLE >::dataID() const {
337
338 return m_event->getName( persKey() );
339}
340
341//
342////////////////////////////////////////////////////////////////////////////////
343
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.
347///
348/// @returns A dummy value. Just to have the same signature as the offline
349/// function.
350///
351template< class STORABLE >
352bool DataLink< STORABLE >::toPersistent() {
353
354 return true;
355}
356
357/// This function just resets the cached pointer when ROOT streams in a new
358/// object from a TBranch.
359///
360/// @returns A dummy value. Just to have the same signature as the offline
361/// function.
362///
363template< class STORABLE >
364bool DataLink< STORABLE >::toTransient() {
365
366 m_object = 0;
367 return true;
368}
369
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.
373///
374template< class STORABLE >
375void DataLink< STORABLE >::findIdentifier() {
376
377 // Allow tests to create a link object, even without setting up an event
378 // object.
379 if (m_event == nullptr) {
380 Warning("DataLink::findIdentifier", "Event object is not available");
381 return;
382 }
383
384 // Ask the event for the identifier of this object:
385 const sgkey_t key = m_event->getKey( m_object );
386 if( ! key ) {
387 Warning( "DataLink::findIdentifier",
388 "Couldn't find the received object in the current event" );
389 }
390
391 // Remember this key:
392 m_persKey = key;
393
394 return;
395}
396
397#endif // ATHLINKS_DATALINK_ICC