1// Dear emacs, this is -*- c++ -*-
3 Copyright (C) 2002-2017 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 is probably the most convenient version of the constructors.
89/// It receives a string identifier (branch name) for the object that the smart
90/// pointer should reference.
92/// @param id A string identifier for the object to be referenced
93/// @param event Pointer to an alternative TVirtualEvent object
95template< typename STORABLE >
96DataLink< STORABLE >::DataLink( const ID_type& id, xAOD::TVirtualEvent* event )
97 : DataLinkBase(), m_object( 0 ), m_event( event ) {
99 // Get the active event if the user didn't specify one explicitly:
101 m_event = xAOD::TActiveEvent::event();
104 // Translate the id into a hashed key:
105 m_persKey = m_event->getHash( id );
108/// This is the most cost-effective of the constructors after the default
109/// one. It relies on the user knowing exactly what hashed key to ask for
110/// for the target object.
112/// @param key A hashed key identifying the object to be referenced
113/// @param event Pointer to an alternative TVirtualEvent object
115template< typename STORABLE >
116DataLink< STORABLE >::DataLink( sgkey_t key, xAOD::TVirtualEvent* event )
117 : DataLinkBase( key ), m_object( 0 ), m_event( event ) {
119 // Get the active event if the user didn't specify one explicitly:
121 m_event = xAOD::TActiveEvent::event();
125/// Simple copy-constructor. It just copies the persistent information
126/// from the base class together with the TVirtualEvent pointer that the parent
129/// @param parent The parent object to be copied
131template< typename STORABLE >
132template< typename T >
133DataLink< STORABLE >::DataLink( const DataLink< T >& parent )
134 : DataLinkBase( parent ), m_object( 0 ), m_event( parent.m_event ) {
139////////////////////////////////////////////////////////////////////////////////
141////////////////////////////////////////////////////////////////////////////////
143// Implementation of the different setter functions
146/// This function should be used to set up the object when your code has a
147/// reference to the target object.
149/// The function will throw an exception if the supplied object can't be found
150/// in the current event.
152/// @param data A reference to the target object
154template< typename STORABLE >
155void DataLink< STORABLE >::toStorableObject( const_reference data ) {
157 // Remember the pointer:
160 // Now try to look up the object in the store:
166/// This function sets up the object to point at the default object of the
167/// template type in the event. It can be useful when only one object of a
168/// given type is available.
170template< typename STORABLE >
171void DataLink< STORABLE >::toDefaultObject() {
173 // Reset the cached pointer:
176 // Set a special value for the persistent variable:
177 setPersKey( xAOD::TVirtualEvent::DEFAULT_KEY );
182/// This is one of the more convenient functions. It sets up the smart pointer
183/// using a user-readable string idetifier for the target object.
185/// @param id A string identifier (branch name) for the target object
187template< typename STORABLE >
188void DataLink< STORABLE >::toIdentifiedObject( const ID_type& id ) {
190 // Check if we have a valid event:
192 throw std::runtime_error( "DataLink::toIdentifiedObject: No valid "
193 "TVirtualEvent pointer available (key: " +
197 // Reset the cached pointer:
200 // Set the persistent key using this identifier:
201 m_persKey = m_event->getHash( id );
206/// This function hardly has to do anything. It just sets the received key as
207/// the persistent information for the object, and resets its internals.
209/// @param key The hashed key for the target object
211template< typename STORABLE >
212void DataLink< STORABLE >::toIdentifiedObject( sgkey_t key ) {
214 // Reset the cached pointer:
217 // Set the persistent key:
224////////////////////////////////////////////////////////////////////////////////
226////////////////////////////////////////////////////////////////////////////////
228// Implementation of the different accessor functions
231/// This operator can be used to get a constant reference to the object.
232/// In most cases though one should probably use the -> operator instead.
233/// The code throws an exception if the target object is not available.
235/// @returns A constant reference to the target object if available
237template< class STORABLE >
238typename DataLink< STORABLE >::const_reference
239DataLink< STORABLE >::operator*() const {
241 // See if we have a valid object:
242 const_pointer ptr = cptr();
244 // If not, throw an exception:
246 throw std::runtime_error( "DataLink::operator*: No valid target for the "
250 // Return the reference. Notice that we're not using the temporary variable
255/// This function is doing most of the heavy lifting. It interacts with the
256/// TVirtualEvent object to deliver a pointer to the target object to the user.
258/// @returns A constant pointer to the target object if available, a
259/// null pointer if not
261template< class STORABLE >
262typename DataLink< STORABLE >::const_pointer
263DataLink< STORABLE >::cptr() const {
265 // If the object is already cached, return right away:
266 if( m_object || ( ! m_event ) ) return m_object;
268 /// Default key, calculated just once:
269 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
270 xAOD::TVirtualEvent::KEY_MASK );
272 // If the key is nonsensical, fail silently:
273 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
277 // Ask the event object for the object in question:
278 if( ! m_event->retrieve( m_object, m_persKey ) ) {
282 // Return what we acquired:
286template< class STORABLE >
287bool DataLink< STORABLE >::isValid() const {
289 // If we have an object already cached, the answer is easy:
294 // If there's no event object, we won't be able to retrieve anything:
299 /// Default key, calculated just once:
300 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
301 xAOD::TVirtualEvent::KEY_MASK );
303 // Check for non-valid keys:
304 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
308 // Try retrieving the object:
309 if( ! m_event->retrieve( m_object, m_persKey, true ) ) {
313 // Apparently the link can be de-referenced:
317template< typename STORABLE >
318const typename DataLink< STORABLE >::ID_type&
319DataLink< STORABLE >::dataID() const {
321 return m_event->getName( persKey() );
325////////////////////////////////////////////////////////////////////////////////
327/// This function is just here to enable us compiling the same EDM code as
328/// we do offline. We don't actually need to prepare this object for being
329/// written out, it's always in a consistent state.
331/// @returns A dummy value. Just to have the same signature as the offline
334template< class STORABLE >
335bool DataLink< STORABLE >::toPersistent() {
340/// This function just resets the cached pointer when ROOT streams in a new
341/// object from a TBranch.
343/// @returns A dummy value. Just to have the same signature as the offline
346template< class STORABLE >
347bool DataLink< STORABLE >::toTransient() {
353/// This function is used internally to find the hashed identifier for an object
354/// that was given to the DataLink either by reference or pointer. It throws an
355/// exception if the object can't be found in the event.
357template< class STORABLE >
358void DataLink< STORABLE >::findIdentifier() {
360 // Ask the event for the identifier of this object:
361 const sgkey_t key = m_event->getKey( m_object );
363 Warning( "DataLink::findIdentifier",
364 "Couldn't find the received object in the current event" );
367 // Remember this key:
373#endif // ATHLINKS_DATALINK_ICC