File indexing completed on 2025-01-18 09:57:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
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 }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 template <typename T>
0106 class DataObjectHandle : public DataObjectHandleBase {
0107 public:
0108 using DataObjectHandleBase::DataObjectHandleBase;
0109
0110
0111
0112
0113 T* get() const { return get( true ); }
0114
0115
0116
0117
0118
0119 T* getIfExists() const { return get( false ); }
0120
0121
0122
0123
0124 bool exist() const { return get( false ) != nullptr; }
0125
0126
0127
0128
0129 T* getOrCreate() const;
0130
0131
0132
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
0155
0156
0157
0158
0159
0160 template <typename T>
0161 T* DataObjectHandle<T>::get( bool mustExist ) const {
0162 auto dataObj = fetch();
0163 if ( !dataObj ) {
0164 if ( mustExist ) {
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
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
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
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
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
0282 template <typename T>
0283 class DataObjectHandle<AnyDataWrapper<T>> : public DataObjectHandleBase {
0284 public:
0285 using DataObjectHandleBase::DataObjectHandleBase;
0286
0287
0288
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
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
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
0339 template <typename View, typename Owned>
0340 class DataObjectHandle<AnyDataWithViewWrapper<View, Owned>> : public DataObjectHandleBase {
0341 public:
0342 using DataObjectHandleBase::DataObjectHandleBase;
0343
0344
0345
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
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
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
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 }
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
0415
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
0437
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 };