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
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 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 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 template <typename T>
0110 class DataObjectHandle : public DataObjectHandleBase {
0111 public:
0112 using DataObjectHandleBase::DataObjectHandleBase;
0113
0114
0115
0116
0117 T* get() const { return get( true ); }
0118
0119
0120
0121
0122
0123 T* getIfExists() const { return get( false ); }
0124
0125
0126
0127
0128 bool exist() const { return get( false ) != nullptr; }
0129
0130
0131
0132
0133 T* getOrCreate() const;
0134
0135
0136
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
0159
0160
0161
0162
0163
0164 template <typename T>
0165 T* DataObjectHandle<T>::get( bool mustExist ) const {
0166 auto dataObj = fetch();
0167 if ( !dataObj ) {
0168 if ( mustExist ) {
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
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
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
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
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
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
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
0329 template <typename T>
0330 class DataObjectHandle<AnyDataWrapper<T>> : public DataObjectHandleBase {
0331 public:
0332 using DataObjectHandleBase::DataObjectHandleBase;
0333
0334
0335
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
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
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
0386 template <typename View, typename Owned>
0387 class DataObjectHandle<AnyDataWithViewWrapper<View, Owned>> : public DataObjectHandleBase {
0388 public:
0389 using DataObjectHandleBase::DataObjectHandleBase;
0390
0391
0392
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
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
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
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 }
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
0462
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
0484
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 };