Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/GaudiKernel/DataObjectHandle.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2024 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   template <typename T, typename U>
0086   struct Payload_helper<Gaudi::DataHandle::Reader, std::optional<Gaudi::NamedRange_<T>>, U> {
0087     using type = std::optional<Gaudi::NamedRange_<T>>;
0088   };
0089 
0090   template <Gaudi::DataHandle::Mode mode, typename T, typename U = T>
0091   using Payload_t = typename Payload_helper<mode, T, U>::type;
0092 
0093 } // namespace details
0094 
0095 //---------------------------------------------------------------------------
0096 
0097 /** DataObjectHandle.h GaudiKernel/DataObjectHandle.h
0098  *
0099  * Templated Handle class for objects in the event store
0100  *
0101  * Inheritance: DataHandle->DataObjectHandleBase->DataObjectHandle<T>
0102  *
0103  * @author Charles Leggett
0104  * @date   2015-09-01
0105  */
0106 
0107 //---------------------------------------------------------------------------
0108 
0109 template <typename T>
0110 class DataObjectHandle : public DataObjectHandleBase {
0111 public:
0112   using DataObjectHandleBase::DataObjectHandleBase;
0113 
0114   /**
0115    * Retrieve object from transient data store
0116    */
0117   T* get() const { return get( true ); }
0118 
0119   /**
0120    * Bypass check of existence of object in transient store
0121    * Only uses main location of the
0122    */
0123   T* getIfExists() const { return get( false ); }
0124 
0125   /**
0126    * Check the existence of the object in the transient store
0127    */
0128   bool exist() const { return get( false ) != nullptr; }
0129 
0130   /**
0131    * Get object from store or create a new one if it doesn't exist
0132    */
0133   T* getOrCreate() const;
0134 
0135   /**
0136    * Register object in transient store
0137    */
0138   T* put( std::unique_ptr<T> object ) const;
0139 
0140   [[deprecated( "please pass a std::unique_ptr instead of a raw pointer" )]] T* put( T* object ) const {
0141     return put( std::unique_ptr<T>( object ) );
0142   }
0143 
0144   std::string pythonRepr() const override {
0145     auto repr = DataObjectHandleBase::pythonRepr();
0146     boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
0147     return repr;
0148   }
0149 
0150 private:
0151   T*           get( bool mustExist ) const;
0152   mutable bool m_goodType = false;
0153 };
0154 
0155 //---------------------------------------------------------------------------
0156 //
0157 /**
0158  * Try to retrieve from the transient store. If the retrieval succeded and
0159  * this is the first time we retrieve, perform a dynamic cast to the desired
0160  * object. Then finally set the handle as Read.
0161  * If this is not the first time we cast and the cast worked, just use the
0162  * static cast: we do not need the checks of the dynamic cast for every access!
0163  */
0164 template <typename T>
0165 T* DataObjectHandle<T>::get( bool mustExist ) const {
0166   auto dataObj = fetch();
0167   if ( !dataObj ) {
0168     if ( mustExist ) { // Problems in getting from the store
0169       throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0170                             m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0171     }
0172     return nullptr;
0173   }
0174   if ( !m_goodType ) m_goodType = ::details::verifyType<T>( dataObj );
0175   return static_cast<T*>( dataObj );
0176 }
0177 
0178 //---------------------------------------------------------------------------
0179 template <typename T>
0180 T* DataObjectHandle<T>::put( std::unique_ptr<T> objectp ) const {
0181   assert( m_init );
0182   StatusCode sc = m_EDS->registerObject( objKey(), objectp.get() );
0183   if ( !sc.isSuccess() ) { throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", sc ); }
0184   return objectp.release();
0185 }
0186 
0187 //---------------------------------------------------------------------------
0188 template <typename T>
0189 T* DataObjectHandle<T>::getOrCreate() const {
0190   T* obj = get( false );
0191   return obj ? obj : put( std::make_unique<T>() );
0192 }
0193 
0194 //---------------------------------------------------------------------------
0195 /// specialization for Range_
0196 
0197 template <typename T>
0198 class DataObjectHandle<Gaudi::Range_<T>> : public DataObjectHandleBase {
0199 public:
0200   using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
0201   using Range     = Gaudi::Range_<typename ValueType::ConstVector>;
0202 
0203   using DataObjectHandleBase::DataObjectHandleBase;
0204 
0205   /**
0206    * Retrieve object from transient data store
0207    */
0208   Range get() const;
0209 
0210   std::string pythonRepr() const override {
0211     auto repr = DataObjectHandleBase::pythonRepr();
0212     boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::Range_<T> ) ) );
0213     return repr;
0214   }
0215 
0216 private:
0217   mutable ::details::Converter_t<Range> m_converter = nullptr;
0218 };
0219 
0220 template <typename ValueType>
0221 auto DataObjectHandle<Gaudi::Range_<ValueType>>::get() const -> Range {
0222   auto dataObj = fetch();
0223   if ( !dataObj ) {
0224     throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0225                           m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0226   }
0227   if ( !m_converter ) {
0228     m_converter = ::details::select_range_converter<ValueType>( dataObj );
0229     if ( !m_converter ) {
0230       throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
0231                                 ")" + " cannot be obtained from object in event store" + " (" +
0232                                 System::typeinfoName( typeid( *dataObj ) ) + ").",
0233                             "Wrong DataObjectType", StatusCode::FAILURE );
0234     }
0235   }
0236   return ( *m_converter )( dataObj );
0237 }
0238 
0239 //---------------------------------------------------------------------------
0240 /// specialization for NamedRange_
0241 
0242 template <typename T>
0243 class DataObjectHandle<Gaudi::NamedRange_<T>> : public DataObjectHandleBase {
0244 public:
0245   using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
0246   using Range     = Gaudi::NamedRange_<typename ValueType::ConstVector>;
0247 
0248   using DataObjectHandleBase::DataObjectHandleBase;
0249 
0250   /**
0251    * Retrieve object from transient data store
0252    */
0253   Range get() const;
0254 
0255   std::string pythonRepr() const override {
0256     auto repr = DataObjectHandleBase::pythonRepr();
0257     boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::NamedRange_<T> ) ) );
0258     return repr;
0259   }
0260 
0261 private:
0262   mutable ::details::Converter_t<Range> m_converter = nullptr;
0263 };
0264 
0265 template <typename ValueType>
0266 auto DataObjectHandle<Gaudi::NamedRange_<ValueType>>::get() const -> Range {
0267   auto dataObj = fetch();
0268   if ( !dataObj ) {
0269     throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0270                           m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0271   }
0272   if ( !m_converter ) {
0273     m_converter = ::details::select_range_converter<ValueType, Range>( dataObj );
0274     if ( !m_converter ) {
0275       throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
0276                                 ")" + " cannot be obtained from object in event store" + " (" +
0277                                 System::typeinfoName( typeid( *dataObj ) ) + ").",
0278                             "Wrong DataObjectType", StatusCode::FAILURE );
0279     }
0280   }
0281   return ( *m_converter )( dataObj );
0282 }
0283 
0284 //
0285 //---------------------------------------------------------------------------
0286 /// specialization for optional<NamedRange_>
0287 
0288 template <typename T>
0289 class DataObjectHandle<std::optional<Gaudi::NamedRange_<T>>> : public DataObjectHandleBase {
0290 public:
0291   using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
0292   using Range     = Gaudi::NamedRange_<typename ValueType::ConstVector>;
0293 
0294   using DataObjectHandleBase::DataObjectHandleBase;
0295 
0296   /**
0297    * Retrieve object from transient data store
0298    */
0299   std::optional<Range> get() const;
0300 
0301   std::string pythonRepr() const override {
0302     auto repr = DataObjectHandleBase::pythonRepr();
0303     boost::replace_all( repr, default_type, System::typeinfoName( typeid( std::optional<Gaudi::NamedRange_<T>> ) ) );
0304     return repr;
0305   }
0306 
0307 private:
0308   mutable ::details::Converter_t<Range> m_converter = nullptr;
0309 };
0310 
0311 template <typename ValueType>
0312 auto DataObjectHandle<std::optional<Gaudi::NamedRange_<ValueType>>>::get() const -> std::optional<Range> {
0313   auto dataObj = fetch();
0314   if ( !dataObj ) return std::nullopt;
0315   if ( !m_converter ) {
0316     m_converter = ::details::select_range_converter<ValueType, Range>( dataObj );
0317     if ( !m_converter ) {
0318       throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
0319                                 ")" + " cannot be obtained from object in event store" + " (" +
0320                                 System::typeinfoName( typeid( *dataObj ) ) + ").",
0321                             "Wrong DataObjectType", StatusCode::FAILURE );
0322     }
0323   }
0324   return ( *m_converter )( dataObj );
0325 }
0326 
0327 //---------------------------------------------------------------------------
0328 /// specialization for AnyDataWrapper
0329 template <typename T>
0330 class DataObjectHandle<AnyDataWrapper<T>> : public DataObjectHandleBase {
0331 public:
0332   using DataObjectHandleBase::DataObjectHandleBase;
0333 
0334   /**
0335    * Retrieve object from transient data store
0336    */
0337   T* get() const { return &_get( true )->getData(); }
0338   T* getIfExists() const {
0339     auto data = _get( false );
0340     return data ? &data->getData() : nullptr;
0341   }
0342 
0343   /**
0344    * Register object in transient store
0345    */
0346   const T* put( T&& obj ) const {
0347     assert( m_init );
0348     auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
0349     if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
0350       throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWrapper<T>>::put", sc );
0351     }
0352     return &objectp.release()->getData();
0353   }
0354 
0355   /**
0356    * Size of boxed item, if boxed item has a 'size' method
0357    */
0358   std::optional<std::size_t> size() const { return _get()->size(); }
0359 
0360   std::string pythonRepr() const override {
0361     auto repr = DataObjectHandleBase::pythonRepr();
0362     boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
0363     return repr;
0364   }
0365 
0366 private:
0367   AnyDataWrapper<T>* _get( bool mustExist ) const {
0368     auto obj = fetch();
0369     if ( !obj ) {
0370       if ( mustExist ) {
0371         throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0372                               m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0373 
0374       } else {
0375         return nullptr;
0376       }
0377     }
0378     if ( !m_goodType ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
0379     return static_cast<AnyDataWrapper<T>*>( obj );
0380   }
0381   mutable bool m_goodType = false;
0382 };
0383 
0384 //---------------------------------------------------------------------------
0385 /// specialization for AnyDataWithViewWrapper
0386 template <typename View, typename Owned>
0387 class DataObjectHandle<AnyDataWithViewWrapper<View, Owned>> : public DataObjectHandleBase {
0388 public:
0389   using DataObjectHandleBase::DataObjectHandleBase;
0390 
0391   /**
0392    * Retrieve object from transient data store
0393    */
0394   View* get() const { return &_get( true )->getData(); }
0395   View* getIfExists() const {
0396     auto data = _get( false );
0397     return data ? &data->getData() : nullptr;
0398   }
0399 
0400   /**
0401    * Register object in transient store
0402    */
0403   const View* put( std::unique_ptr<AnyDataWithViewWrapper<View, Owned>> objectp ) const {
0404     assert( m_init );
0405     if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
0406       throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWithViewWrapper<T>::put", sc );
0407     }
0408     return &objectp.release()->getData();
0409   }
0410   const View* put( Owned&& obj ) const {
0411     return put( std::make_unique<AnyDataWithViewWrapper<View, Owned>>( std::move( obj ) ) );
0412   }
0413 
0414   /**
0415    * Size of boxed item, if boxed item has a 'size' method
0416    */
0417   std::optional<std::size_t> size() const { return _get()->size(); }
0418 
0419   std::string pythonRepr() const override {
0420     auto repr = DataObjectHandleBase::pythonRepr();
0421     boost::replace_all( repr, default_type, System::typeinfoName( typeid( View ) ) );
0422     return repr;
0423   }
0424 
0425 private:
0426   AnyDataWithViewWrapper<View, Owned>* _get( bool mustExist ) const {
0427     auto obj = fetch();
0428     if ( !obj ) {
0429       if ( mustExist ) {
0430         throw GaudiException( "Cannot retrieve \'" + objKey() + "\' from transient store.",
0431                               m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
0432 
0433       } else {
0434         return nullptr;
0435       }
0436     }
0437     if ( !m_goodType ) m_goodType = ::details::verifyType<AnyDataWithViewWrapper<View, Owned>>( obj );
0438     return static_cast<AnyDataWithViewWrapper<View, Owned>*>( obj );
0439   }
0440   mutable bool m_goodType = false;
0441 };
0442 
0443 //---------------------------- user-facing interface ----------
0444 namespace details {
0445   template <typename T, typename U = T>
0446   using WriteHandle = DataObjectHandle<Payload_t<Gaudi::DataHandle::Writer, T, U>>;
0447   template <typename T, typename U = T>
0448   using ReadHandle = DataObjectHandle<Payload_t<Gaudi::DataHandle::Reader, T, U>>;
0449 } // namespace details
0450 
0451 template <typename T>
0452 class DataObjectReadHandle : public ::details::ReadHandle<T> {
0453   template <typename... Args, std::size_t... Is>
0454   DataObjectReadHandle( std::tuple<Args...>&& args, std::index_sequence<Is...> )
0455       : DataObjectReadHandle( std::get<Is>( std::move( args ) )... ) {}
0456 
0457 public:
0458   DataObjectReadHandle( const DataObjID& k, IDataHandleHolder* owner )
0459       : ::details::ReadHandle<T>{ k, Gaudi::DataHandle::Reader, owner } {}
0460 
0461   /// Autodeclaring constructor with property name, mode, key and documentation.
0462   /// @note the use std::enable_if is required to avoid ambiguities
0463   template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
0464   DataObjectReadHandle( OWNER* owner, std::string propertyName, K key = {}, std::string doc = "" )
0465       : ::details::ReadHandle<T>( owner, Gaudi::DataHandle::Reader, std::move( propertyName ), std::move( key ),
0466                                   std::move( doc ) ) {}
0467 
0468   template <typename... Args>
0469   DataObjectReadHandle( std::tuple<Args...>&& args )
0470       : DataObjectReadHandle( std::move( args ), std::index_sequence_for<Args...>{} ) {}
0471 };
0472 
0473 template <typename T, typename U = T>
0474 class DataObjectWriteHandle : public ::details::WriteHandle<T, U> {
0475   template <typename... Args, std::size_t... Is>
0476   DataObjectWriteHandle( std::tuple<Args...>&& args, std::index_sequence<Is...> )
0477       : DataObjectWriteHandle( std::get<Is>( std::move( args ) )... ) {}
0478 
0479 public:
0480   DataObjectWriteHandle( const DataObjID& k, IDataHandleHolder* owner )
0481       : ::details::WriteHandle<T, U>{ k, Gaudi::DataHandle::Writer, owner } {}
0482 
0483   /// Autodeclaring constructor with property name, mode, key and documentation.
0484   /// @note the use std::enable_if is required to avoid ambiguities
0485   template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
0486   DataObjectWriteHandle( OWNER* owner, std::string propertyName, K key = {}, std::string doc = "" )
0487       : ::details::WriteHandle<T, U>( owner, Gaudi::DataHandle::Writer, std::move( propertyName ), std::move( key ),
0488                                       std::move( doc ) ) {}
0489 
0490   template <typename... Args>
0491   DataObjectWriteHandle( std::tuple<Args...>&& args )
0492       : DataObjectWriteHandle( std::move( args ), std::index_sequence_for<Args...>{} ) {}
0493 };