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.
26 template< typename STORABLE >
27 DataLink< 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
37 template< typename STORABLE >
38 DataLink< 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
52 template< typename STORABLE >
53 DataLink< 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
75 template< typename STORABLE >
76 DataLink< 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
95 template< typename STORABLE >
96 DataLink< 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
115 template< typename STORABLE >
116 DataLink< 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
131 template< typename STORABLE >
132 template< typename T >
133 DataLink< 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
154 template< typename STORABLE >
155 void 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.
170 template< typename STORABLE >
171 void 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
187 template< typename STORABLE >
188 void 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
211 template< typename STORABLE >
212 void 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
237 template< class STORABLE >
238 typename DataLink< STORABLE >::const_reference
239 DataLink< 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
261 template< class STORABLE >
262 typename DataLink< STORABLE >::const_pointer
263 DataLink< 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:
286 template< class STORABLE >
287 bool 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:
317 template< typename STORABLE >
318 const typename DataLink< STORABLE >::ID_type&
319 DataLink< 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
334 template< class STORABLE >
335 bool 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
346 template< class STORABLE >
347 bool 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.
357 template< class STORABLE >
358 void 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