Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:37

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #pragma once
0012 
0013 #include "GaudiKernel/AnyDataWrapper.h"
0014 #include "GaudiKernel/DataObjectHandleBase.h"
0015 #include "GaudiKernel/GaudiException.h"
0016 #include "GaudiKernel/IDataHandleHolder.h"
0017 #include "GaudiKernel/IProperty.h"
0018 #include "GaudiKernel/IRegistry.h"
0019 #include "GaudiKernel/NamedRange.h"
0020 #include "boost/algorithm/string/replace.hpp"
0021 #include <type_traits>
0022 
0023 //---------------------------------------------------------------------------
0024 //
0025 namespace details {
0026   template <typename T>
0027   using Converter_t = T ( * )( const DataObject* );
0028 
0029   template <typename Range, typename StorageType>
0030   Range make_range( const DataObject* obj ) {
0031     auto c = static_cast<const StorageType*>( obj );
0032     if ( !c ) return Range();
0033     using std::begin;
0034     using std::end;
0035     auto first  = begin( *c );
0036     auto last   = end( *c );
0037     auto _first = reinterpret_cast<typename Range::const_iterator*>( &first );
0038     auto _last  = reinterpret_cast<typename Range::const_iterator*>( &last );
0039     return Range( *_first, *_last );
0040   }
0041 
0042   template <typename ValueType, typename Range = Gaudi::Range_<typename ValueType::ConstVector>>
0043   Converter_t<Range> select_range_converter( const DataObject* obj ) {
0044     using Selection = typename ValueType::Selection;
0045     auto sel        = dynamic_cast<const Selection*>( obj );
0046     if ( sel ) return &make_range<Range, typename ValueType::Selection>;
0047     auto con = dynamic_cast<std::add_const_t<typename ValueType::Container>*>( obj );
0048     if ( con ) return &make_range<Range, typename ValueType::Container>;
0049     return nullptr;
0050   }
0051 
0052   template <typename T>
0053   bool verifyType( const DataObject* dataObj ) {
0054     using Type = std::add_const_t<T>;
0055     assert( dataObj != nullptr );
0056     auto obj = dynamic_cast<Type*>( dataObj );
0057     bool ok  = ( obj != nullptr );
0058     if ( !ok ) {
0059       const auto* registry = dataObj->registry();
0060       throw GaudiException( "The type expected for " + registry->identifier() + " is " +
0061                                 System::typeinfoName( typeid( Type ) ) +
0062                                 " and is different from the one of the object in the store which is " +
0063                                 System::typeinfoName( typeid( *dataObj ) ) + ".",
0064                             "Wrong DataObjectType", StatusCode::FAILURE );
0065     }
0066     assert( obj == static_cast<Type*>( dataObj ) );
0067     return ok;
0068   }
0069 
0070   template <Gaudi::DataHandle::Mode, typename T, typename U>
0071   struct Payload_helper {
0072     using type =
0073         std::conditional_t<std::is_base_of_v<DataObject, T> && std::is_same_v<T, U>, T,
0074                            std::conditional_t<std::is_same_v<T, U>, AnyDataWrapper<std::remove_const_t<T>>,
0075                                               AnyDataWithViewWrapper<std::remove_const_t<T>, std::remove_const_t<U>>>>;
0076   };
0077   template <typename T, typename U>
0078   struct Payload_helper<Gaudi::DataHandle::Reader, Gaudi::Range_<T>, U> {
0079     using type = Gaudi::Range_<T>;
0080   };
0081   template <typename T, typename U>
0082   struct Payload_helper<Gaudi::DataHandle::Reader, Gaudi::NamedRange_<T>, U> {
0083     using type = Gaudi::NamedRange_<T>;
0084   };
0085 
0086   template <Gaudi::DataHandle::Mode mode, typename T, typename U = T>
0087   using Payload_t = typename Payload_helper<mode, T, U>::type;
0088 
0089 } // namespace details
0090 
0091 //---------------------------------------------------------------------------
0092 
0093 /** DataObjectHandle.h GaudiKernel/DataObjectHandle.h
0094  *
0095  * Templated Handle class for objects in the event store
0096  *
0097  * Inheritance: DataHandle->DataObjectHandleBase->DataObjectHandle<T>
0098  *
0099  * @author Charles Leggett
0100  * @date   2015-09-01
0101  */
0102 
0103 //---------------------------------------------------------------------------
0104 
0105 template <typename T>
0106 class DataObjectHandle : public DataObjectHandleBase {
0107 public:
0108   using DataObjectHandleBase::DataObjectHandleBase;
0109 
0110   /**
0111    * Retrieve object from transient data store
0112    */
0113   T* get() const { return get( true ); }
0114 
0115   /**
0116    * Bypass check of existence of object in transient store
0117    * Only uses main location of the
0118    */
0119   T* getIfExists() const { return get( false ); }
0120 
0121   /**
0122    * Check the existence of the object in the transient store
0123    */
0124   bool exist() const { return get( false ) != nullptr; }
0125 
0126   /**
0127    * Get object from store or create a new one if it doesn't exist
0128    */
0129   T* getOrCreate() const;
0130 
0131   /**
0132    * Register object in transient store
0133    */
0134   T* put( std::unique_ptr<T> object ) const;
0135 
0136   [[deprecated( "please pass a std::unique_ptr instead of a raw pointer" )]] T* put( T* object ) const {
0137     return put( std::unique_ptr<T>( object ) );
0138   }
0139 
0140   std::string pythonRepr() const override {
0141     auto repr = DataObjectHandleBase::pythonRepr();
0142     boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
0143     return repr;
0144   }
0145 
0146 private:
0147   T*           get( bool mustExist ) const;
0148   mutable bool m_goodType = false;
0149 };
0150 
0151 //---------------------------------------------------------------------------
0152 //
0153 /**
0154  * Try to retrieve from the transient store. If the retrieval succeded and
0155  * this is the first time we retrieve, perform a dynamic cast to the desired
0156  * object. Then finally set the handle as Read.
0157  * If this is not the first time we cast and the cast worked, just use the
0158  * static cast: we do not need the checks of the dynamic cast for every access!
0159  */
0160 template <typename T>
0161 T* DataObjectHandle<T>::get( bool mustExist ) const {
0162   auto dataObj = fetch();
0163   if ( !dataObj ) {
0164     if ( mustExist ) { // Problems in getting from the store
0165       throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0166                             m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0167     }
0168     return nullptr;
0169   }
0170   if ( !m_goodType ) m_goodType = ::details::verifyType<T>( dataObj );
0171   return static_cast<T*>( dataObj );
0172 }
0173 
0174 //---------------------------------------------------------------------------
0175 template <typename T>
0176 T* DataObjectHandle<T>::put( std::unique_ptr<T> objectp ) const {
0177   assert( m_init );
0178   StatusCode sc = m_EDS->registerObject( objKey(), objectp.get() );
0179   if ( !sc.isSuccess() ) { throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", sc ); }
0180   return objectp.release();
0181 }
0182 
0183 //---------------------------------------------------------------------------
0184 template <typename T>
0185 T* DataObjectHandle<T>::getOrCreate() const {
0186   T* obj = get( false );
0187   return obj ? obj : put( std::make_unique<T>() );
0188 }
0189 
0190 //---------------------------------------------------------------------------
0191 /// specialization for Range_
0192 
0193 template <typename T>
0194 class DataObjectHandle<Gaudi::Range_<T>> : public DataObjectHandleBase {
0195 public:
0196   using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
0197   using Range     = Gaudi::Range_<typename ValueType::ConstVector>;
0198 
0199   using DataObjectHandleBase::DataObjectHandleBase;
0200 
0201   /**
0202    * Retrieve object from transient data store
0203    */
0204   Range get() const;
0205 
0206   std::string pythonRepr() const override {
0207     auto repr = DataObjectHandleBase::pythonRepr();
0208     boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::Range_<T> ) ) );
0209     return repr;
0210   }
0211 
0212 private:
0213   mutable ::details::Converter_t<Range> m_converter = nullptr;
0214 };
0215 
0216 template <typename ValueType>
0217 auto DataObjectHandle<Gaudi::Range_<ValueType>>::get() const -> Range {
0218   auto dataObj = fetch();
0219   if ( !dataObj ) {
0220     throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0221                           m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0222   }
0223   if ( !m_converter ) {
0224     m_converter = ::details::select_range_converter<ValueType>( dataObj );
0225     if ( !m_converter ) {
0226       throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
0227                                 ")" + " cannot be obtained from object in event store" + " (" +
0228                                 System::typeinfoName( typeid( *dataObj ) ) + ").",
0229                             "Wrong DataObjectType", StatusCode::FAILURE );
0230     }
0231   }
0232   return ( *m_converter )( dataObj );
0233 }
0234 
0235 //---------------------------------------------------------------------------
0236 /// specialization for NamedRange_
0237 
0238 template <typename T>
0239 class DataObjectHandle<Gaudi::NamedRange_<T>> : public DataObjectHandleBase {
0240 public:
0241   using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
0242   using Range     = Gaudi::NamedRange_<typename ValueType::ConstVector>;
0243 
0244   using DataObjectHandleBase::DataObjectHandleBase;
0245 
0246   /**
0247    * Retrieve object from transient data store
0248    */
0249   Range get() const;
0250 
0251   std::string pythonRepr() const override {
0252     auto repr = DataObjectHandleBase::pythonRepr();
0253     boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::NamedRange_<T> ) ) );
0254     return repr;
0255   }
0256 
0257 private:
0258   mutable ::details::Converter_t<Range> m_converter = nullptr;
0259 };
0260 
0261 template <typename ValueType>
0262 auto DataObjectHandle<Gaudi::NamedRange_<ValueType>>::get() const -> Range {
0263   auto dataObj = fetch();
0264   if ( !dataObj ) {
0265     throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0266                           m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0267   }
0268   if ( !m_converter ) {
0269     m_converter = ::details::select_range_converter<ValueType, Range>( dataObj );
0270     if ( !m_converter ) {
0271       throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
0272                                 ")" + " cannot be obtained from object in event store" + " (" +
0273                                 System::typeinfoName( typeid( *dataObj ) ) + ").",
0274                             "Wrong DataObjectType", StatusCode::FAILURE );
0275     }
0276   }
0277   return ( *m_converter )( dataObj );
0278 }
0279 
0280 //---------------------------------------------------------------------------
0281 /// specialization for AnyDataWrapper
0282 template <typename T>
0283 class DataObjectHandle<AnyDataWrapper<T>> : public DataObjectHandleBase {
0284 public:
0285   using DataObjectHandleBase::DataObjectHandleBase;
0286 
0287   /**
0288    * Retrieve object from transient data store
0289    */
0290   T* get() const { return &_get( true )->getData(); }
0291   T* getIfExists() const {
0292     auto data = _get( false );
0293     return data ? &data->getData() : nullptr;
0294   }
0295 
0296   /**
0297    * Register object in transient store
0298    */
0299   const T* put( T&& obj ) const {
0300     assert( m_init );
0301     auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
0302     if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
0303       throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWrapper<T>>::put", sc );
0304     }
0305     return &objectp.release()->getData();
0306   }
0307 
0308   /**
0309    * Size of boxed item, if boxed item has a 'size' method
0310    */
0311   std::optional<std::size_t> size() const { return _get()->size(); }
0312 
0313   std::string pythonRepr() const override {
0314     auto repr = DataObjectHandleBase::pythonRepr();
0315     boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
0316     return repr;
0317   }
0318 
0319 private:
0320   AnyDataWrapper<T>* _get( bool mustExist ) const {
0321     auto obj = fetch();
0322     if ( !obj ) {
0323       if ( mustExist ) {
0324         throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0325                               m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0326 
0327       } else {
0328         return nullptr;
0329       }
0330     }
0331     if ( !m_goodType ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
0332     return static_cast<AnyDataWrapper<T>*>( obj );
0333   }
0334   mutable bool m_goodType = false;
0335 };
0336 
0337 //---------------------------------------------------------------------------
0338 /// specialization for AnyDataWithViewWrapper
0339 template <typename View, typename Owned>
0340 class DataObjectHandle<AnyDataWithViewWrapper<View, Owned>> : public DataObjectHandleBase {
0341 public:
0342   using DataObjectHandleBase::DataObjectHandleBase;
0343 
0344   /**
0345    * Retrieve object from transient data store
0346    */
0347   View* get() const { return &_get( true )->getData(); }
0348   View* getIfExists() const {
0349     auto data = _get( false );
0350     return data ? &data->getData() : nullptr;
0351   }
0352 
0353   /**
0354    * Register object in transient store
0355    */
0356   const View* put( std::unique_ptr<AnyDataWithViewWrapper<View, Owned>> objectp ) const {
0357     assert( m_init );
0358     if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
0359       throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWithViewWrapper<T>::put", sc );
0360     }
0361     return &objectp.release()->getData();
0362   }
0363   const View* put( Owned&& obj ) const {
0364     return put( std::make_unique<AnyDataWithViewWrapper<View, Owned>>( std::move( obj ) ) );
0365   }
0366 
0367   /**
0368    * Size of boxed item, if boxed item has a 'size' method
0369    */
0370   std::optional<std::size_t> size() const { return _get()->size(); }
0371 
0372   std::string pythonRepr() const override {
0373     auto repr = DataObjectHandleBase::pythonRepr();
0374     boost::replace_all( repr, default_type, System::typeinfoName( typeid( View ) ) );
0375     return repr;
0376   }
0377 
0378 private:
0379   AnyDataWithViewWrapper<View, Owned>* _get( bool mustExist ) const {
0380     auto obj = fetch();
0381     if ( !obj ) {
0382       if ( mustExist ) {
0383         throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0384                               m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0385 
0386       } else {
0387         return nullptr;
0388       }
0389     }
0390     if ( !m_goodType ) m_goodType = ::details::verifyType<AnyDataWithViewWrapper<View, Owned>>( obj );
0391     return static_cast<AnyDataWithViewWrapper<View, Owned>*>( obj );
0392   }
0393   mutable bool m_goodType = false;
0394 };
0395 
0396 //---------------------------- user-facing interface ----------
0397 namespace details {
0398   template <typename T, typename U = T>
0399   using WriteHandle = DataObjectHandle<Payload_t<Gaudi::DataHandle::Writer, T, U>>;
0400   template <typename T, typename U = T>
0401   using ReadHandle = DataObjectHandle<Payload_t<Gaudi::DataHandle::Reader, T, U>>;
0402 } // namespace details
0403 
0404 template <typename T>
0405 class DataObjectReadHandle : public ::details::ReadHandle<T> {
0406   template <typename... Args, std::size_t... Is>
0407   DataObjectReadHandle( std::tuple<Args...>&& args, std::index_sequence<Is...> )
0408       : DataObjectReadHandle( std::get<Is>( std::move( args ) )... ) {}
0409 
0410 public:
0411   DataObjectReadHandle( const DataObjID& k, IDataHandleHolder* owner )
0412       : ::details::ReadHandle<T>{ k, Gaudi::DataHandle::Reader, owner } {}
0413 
0414   /// Autodeclaring constructor with property name, mode, key and documentation.
0415   /// @note the use std::enable_if is required to avoid ambiguities
0416   template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
0417   DataObjectReadHandle( OWNER* owner, std::string propertyName, K key = {}, std::string doc = "" )
0418       : ::details::ReadHandle<T>( owner, Gaudi::DataHandle::Reader, std::move( propertyName ), std::move( key ),
0419                                   std::move( doc ) ) {}
0420 
0421   template <typename... Args>
0422   DataObjectReadHandle( std::tuple<Args...>&& args )
0423       : DataObjectReadHandle( std::move( args ), std::index_sequence_for<Args...>{} ) {}
0424 };
0425 
0426 template <typename T, typename U = T>
0427 class DataObjectWriteHandle : public ::details::WriteHandle<T, U> {
0428   template <typename... Args, std::size_t... Is>
0429   DataObjectWriteHandle( std::tuple<Args...>&& args, std::index_sequence<Is...> )
0430       : DataObjectWriteHandle( std::get<Is>( std::move( args ) )... ) {}
0431 
0432 public:
0433   DataObjectWriteHandle( const DataObjID& k, IDataHandleHolder* owner )
0434       : ::details::WriteHandle<T, U>{ k, Gaudi::DataHandle::Writer, owner } {}
0435 
0436   /// Autodeclaring constructor with property name, mode, key and documentation.
0437   /// @note the use std::enable_if is required to avoid ambiguities
0438   template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
0439   DataObjectWriteHandle( OWNER* owner, std::string propertyName, K key = {}, std::string doc = "" )
0440       : ::details::WriteHandle<T, U>( owner, Gaudi::DataHandle::Writer, std::move( propertyName ), std::move( key ),
0441                                       std::move( doc ) ) {}
0442 
0443   template <typename... Args>
0444   DataObjectWriteHandle( std::tuple<Args...>&& args )
0445       : DataObjectWriteHandle( std::move( args ), std::index_sequence_for<Args...>{} ) {}
0446 };