File indexing completed on 2025-01-18 09:57:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #pragma once
0012
0013 #include "details.h"
0014 #include "utilities.h"
0015 #include <Gaudi/Algorithm.h>
0016 #include <GaudiKernel/FunctionalFilterDecision.h>
0017 #include <functional>
0018 #include <string>
0019 #include <vector>
0020
0021 namespace Gaudi::Functional {
0022
0023 using details::vector_of_const_;
0024
0025 namespace details {
0026 template <typename F, size_t... Is>
0027 auto for_impl( F&& f, std::index_sequence<Is...> ) {
0028 if constexpr ( std::disjunction_v<std::is_void<std::invoke_result_t<F, std::integral_constant<int, Is>>>...> ) {
0029 ( std::invoke( f, std::integral_constant<int, Is>{} ), ... );
0030 } else {
0031 return std::array{ std::invoke( f, std::integral_constant<int, Is>{} )... };
0032 }
0033 }
0034
0035 template <auto N, typename F>
0036 decltype( auto ) for_( F&& f ) {
0037 return for_impl( std::forward<F>( f ), std::make_index_sequence<N>{} );
0038 }
0039
0040 template <typename Sig>
0041 struct is_void_fun : std::false_type {};
0042 template <typename... Args>
0043 struct is_void_fun<void( Args... )> : std::true_type {};
0044 template <typename Sig>
0045 inline constexpr bool is_void_fun_v = is_void_fun<Sig>::value;
0046
0047 template <typename Signature, typename Traits_, bool isLegacy>
0048 struct MergingTransformer;
0049
0050
0051 template <typename Out, typename In, typename Traits_>
0052 struct MergingTransformer<Out( const vector_of_const_<In>& ), Traits_, true>
0053 : DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_> {
0054 private:
0055 using base_class = DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_>;
0056
0057 public:
0058 using KeyValue = typename base_class::KeyValue;
0059 using KeyValues = typename base_class::KeyValues;
0060
0061 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
0062 : base_class( std::move( name ), locator )
0063 , m_inputLocations{ this, inputs.first, details::to_DataObjID( inputs.second ),
0064 [this]( Gaudi::Details::PropertyBase& ) {
0065 this->m_inputs =
0066 make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
0067 if ( std::is_pointer_v<In> ) {
0068
0069
0070 std::for_each( this->m_inputs.begin(), this->m_inputs.end(),
0071 []( auto& h ) { h.setOptional( true ); } );
0072 }
0073 },
0074 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } } {
0075 static_assert( std::is_void_v<Out> );
0076 }
0077
0078 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
0079 : base_class( std::move( name ), locator, output )
0080 , m_inputLocations{ this, inputs.first, details::to_DataObjID( inputs.second ),
0081 [this]( Gaudi::Details::PropertyBase& ) {
0082 this->m_inputs =
0083 make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
0084 if ( std::is_pointer_v<In> ) {
0085
0086
0087 std::for_each( this->m_inputs.begin(), this->m_inputs.end(),
0088 []( auto& h ) { h.setOptional( true ); } );
0089 }
0090 },
0091 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } } {
0092 static_assert( !std::is_void_v<Out> );
0093 }
0094
0095
0096 const std::string& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n].key(); }
0097 unsigned int inputLocationSize() const { return m_inputLocations.value().size(); }
0098
0099
0100 StatusCode execute() override final {
0101 vector_of_const_<In> ins;
0102 ins.reserve( m_inputs.size() );
0103 std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ), details2::get_from_handle<In>{} );
0104 try {
0105 if constexpr ( std::is_void_v<Out> ) {
0106 std::as_const ( *this )( std::as_const( ins ) );
0107 } else {
0108 put( std::get<0>( this->m_outputs ), std::as_const( *this )( std::as_const( ins ) ) );
0109 }
0110 return FilterDecision::PASSED;
0111 } catch ( GaudiException& e ) {
0112 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0113 return e.code();
0114 }
0115 }
0116
0117 virtual Out operator()( const vector_of_const_<In>& inputs ) const = 0;
0118
0119 private:
0120
0121 template <typename T>
0122 using InputHandle_t = InputHandle_t<Traits_, std::remove_pointer_t<T>>;
0123 std::vector<InputHandle_t<In>> m_inputs;
0124 Gaudi::Property<std::vector<DataObjID>> m_inputLocations;
0125
0126
0127 };
0128
0129 template <typename Out, typename... Ins, typename Traits_>
0130 struct MergingTransformer<Out( const vector_of_const_<Ins>&... ), Traits_, false>
0131 : DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_> {
0132
0133 using base_class = DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_>;
0134 using KeyValue = typename base_class::KeyValue;
0135 using KeyValues = typename base_class::KeyValues;
0136 using InKeys = details::RepeatValues_<KeyValues, sizeof...( Ins )>;
0137
0138 private:
0139 auto construct_properties( InKeys inputs ) {
0140 return details::for_<sizeof...( Ins )>( [&]( auto I ) {
0141 constexpr auto i = decltype( I )::value;
0142 auto& ins = std::get<i>( inputs );
0143 return Gaudi::Property<std::vector<DataObjID>>{
0144 this, ins.first, details::to_DataObjID( ins.second ),
0145 [this]( auto&& ) {
0146 auto& handles = std::get<i>( this->m_inputs );
0147 auto& ins = std::get<i>( this->m_inputLocations );
0148 using Handles = typename std::decay_t<decltype( handles )>;
0149 handles = make_vector_of_handles<Handles>( this, ins );
0150 if ( std::is_pointer_v<typename Handles::value_type> ) {
0151
0152
0153
0154 std::for_each( handles.begin(), handles.end(), []( auto& h ) { h.setOptional( true ); } );
0155 }
0156 },
0157 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } };
0158 } );
0159 }
0160
0161 public:
0162 MergingTransformer( std::string name, ISvcLocator* locator, InKeys inputs )
0163 : base_class( std::move( name ), locator ), m_inputLocations{ construct_properties( inputs ) } {
0164 static_assert( std::is_void_v<Out> );
0165 }
0166
0167 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
0168 : MergingTransformer{ name, locator, InKeys{ inputs } } {
0169 static_assert( sizeof...( Ins ) == 1 );
0170 }
0171
0172 MergingTransformer( std::string name, ISvcLocator* locator, InKeys inputs, const KeyValue& output )
0173 : base_class( std::move( name ), locator, output ), m_inputLocations{ construct_properties( inputs ) } {
0174 static_assert( !std::is_void_v<Out> );
0175 }
0176
0177 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
0178 : MergingTransformer{ name, locator, InKeys{ inputs }, output } {
0179 static_assert( sizeof...( Ins ) == 1 );
0180 }
0181
0182
0183 const std::string& inputLocation( unsigned int i, unsigned int j ) const {
0184 return m_inputLocations.at( i ).value().at( j ).key();
0185 }
0186 const std::string& inputLocation( unsigned int i ) const {
0187 static_assert( sizeof...( Ins ) == 1 );
0188 return inputLocation( 0, i );
0189 }
0190 unsigned int inputLocationSize( int i = 0 ) const { return m_inputLocations.at( i ).value().size(); }
0191
0192
0193 StatusCode execute( const EventContext& ) const override final {
0194 std::tuple<vector_of_const_<Ins>...> inss;
0195 details::for_<sizeof...( Ins )>( [&]( auto I ) {
0196 constexpr size_t i = decltype( I )::value;
0197 auto& ins = std::get<i>( inss );
0198 auto& handles = std::get<i>( m_inputs );
0199 ins.reserve( handles.size() );
0200 std::transform( handles.begin(), handles.end(), std::back_inserter( ins ),
0201 details::details2::get_from_handle<typename std::decay_t<decltype( ins )>::value_type>{} );
0202 } );
0203 try {
0204 if constexpr ( std::is_void_v<Out> ) {
0205 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); }, inss );
0206 } else {
0207 put( std::get<0>( this->m_outputs ),
0208 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); },
0209 inss ) );
0210 }
0211 return FilterDecision::PASSED;
0212 } catch ( GaudiException& e ) {
0213 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0214 return e.code();
0215 }
0216 }
0217
0218 virtual Out operator()( const vector_of_const_<Ins>&... inputs ) const = 0;
0219
0220 private:
0221
0222 template <typename T>
0223 using InputHandle_t = InputHandle_t<Traits_, std::remove_pointer_t<T>>;
0224 std::tuple<std::vector<InputHandle_t<Ins>>...> m_inputs;
0225 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...( Ins )> m_inputLocations;
0226
0227
0228
0229 };
0230
0231 }
0232
0233 template <typename Signature, typename Traits_ = Traits::useDefaults>
0234 using MergingTransformer = details::MergingTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
0235
0236
0237 template <typename Signature, typename Traits_ = Traits::useDefaults,
0238 typename = std::enable_if_t<details::is_void_fun_v<Signature>>>
0239 using MergingConsumer = details::MergingTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
0240
0241
0242 template <typename Signature, typename Traits_ = Traits::BaseClass_t<Gaudi::Algorithm>>
0243 struct MergingMultiTransformer;
0244
0245 template <typename... Outs, typename... Ins, typename Traits_>
0246 struct MergingMultiTransformer<std::tuple<Outs...>( vector_of_const_<Ins> const&... ), Traits_>
0247 : details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_> {
0248
0249 private:
0250 using base_class = details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_>;
0251
0252 public:
0253 using KeyValue = typename base_class::KeyValue;
0254 using KeyValues = typename base_class::KeyValues;
0255 using InKeys = details::RepeatValues_<KeyValues, sizeof...( Ins )>;
0256 using OutKeys = details::RepeatValues_<KeyValue, sizeof...( Outs )>;
0257 static constexpr size_t n_args = sizeof...( Ins );
0258
0259 MergingMultiTransformer( std::string const& name, ISvcLocator* pSvcLocator, InKeys inputs, OutKeys outputs )
0260 : base_class{ name, pSvcLocator, std::move( outputs ) }
0261 , m_inputLocations{ details::for_<n_args>( [&]( auto I ) {
0262 constexpr auto i = decltype( I )::value;
0263 auto& ins = std::get<i>( inputs );
0264 return Gaudi::Property<std::vector<DataObjID>>{
0265 this, ins.first, details::to_DataObjID( ins.second ),
0266 [this]( auto&& ) {
0267 auto& handles = std::get<i>( this->m_inputs );
0268 auto& ins = std::get<i>( this->m_inputLocations );
0269 using In = typename std::decay_t<decltype( handles )>::value_type;
0270 handles = details::make_vector_of_handles<std::decay_t<decltype( handles )>>( this, ins );
0271 if ( std::is_pointer_v<In> ) {
0272
0273
0274 std::for_each( handles.begin(), handles.end(), []( auto& h ) { h.setOptional( true ); } );
0275 }
0276 },
0277 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } };
0278 } ) } {}
0279
0280 MergingMultiTransformer( std::string const& name, ISvcLocator* pSvcLocator, KeyValues inputs, OutKeys outputs )
0281 : MergingMultiTransformer{ name, pSvcLocator, InKeys{ std::move( inputs ) }, std::move( outputs ) } {
0282 static_assert( sizeof...( Ins ) == 1 );
0283 }
0284
0285
0286 std::string const& inputLocation( unsigned int i, unsigned int j ) const {
0287 return m_inputLocations.at( i ).value().at( j ).key();
0288 }
0289 std::string const& inputLocation( unsigned int j ) const {
0290 static_assert( n_args == 1 );
0291 return inputLocation( 0, j );
0292 }
0293 unsigned int inputLocationSize( int i = 0 ) const { return m_inputLocations.at( i ).value().size(); }
0294
0295
0296 StatusCode execute( EventContext const& ) const override final {
0297 std::tuple<vector_of_const_<Ins>...> inss;
0298 details::for_<sizeof...( Ins )>( [&]( auto I ) {
0299 constexpr size_t i = decltype( I )::value;
0300 auto& ins = std::get<i>( inss );
0301 auto& handles = std::get<i>( m_inputs );
0302 ins.reserve( handles.size() );
0303 std::transform( handles.begin(), handles.end(), std::back_inserter( ins ),
0304 details::details2::get_from_handle<typename std::decay_t<decltype( ins )>::value_type>{} );
0305 } );
0306 try {
0307 std::apply(
0308 [&]( auto&... outhandle ) {
0309 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
0310 std::apply(
0311 [&outhandle...]( auto&&... data ) {
0312 ( details::put( outhandle, std::forward<decltype( data )>( data ) ), ... );
0313 },
0314 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); },
0315 inss ) );
0316 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0317 },
0318 this->m_outputs );
0319 return FilterDecision::PASSED;
0320 } catch ( GaudiException& e ) {
0321 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0322 return e.code();
0323 }
0324 }
0325
0326 virtual std::tuple<Outs...> operator()( const vector_of_const_<Ins>&... inputs ) const = 0;
0327
0328 private:
0329
0330 template <typename T>
0331 using InputHandle_t = details::InputHandle_t<Traits_, typename std::remove_pointer<T>::type>;
0332 std::tuple<std::vector<InputHandle_t<Ins>>...> m_inputs;
0333 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...( Ins )> m_inputLocations;
0334
0335
0336
0337 };
0338
0339
0340 template <typename Signature, typename Traits_ = Traits::BaseClass_t<Gaudi::Algorithm>>
0341 struct MergingMultiTransformerFilter;
0342
0343 template <typename... Outs, typename In, typename Traits_>
0344 struct MergingMultiTransformerFilter<std::tuple<Outs...>( vector_of_const_<In> const& ), Traits_>
0345 : details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_> {
0346
0347 private:
0348 using base_class = details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_>;
0349
0350 public:
0351 using KeyValue = typename base_class::KeyValue;
0352 using KeyValues = typename base_class::KeyValues;
0353 using OutKeys = details::RepeatValues_<KeyValue, sizeof...( Outs )>;
0354
0355 MergingMultiTransformerFilter( std::string const& name, ISvcLocator* locator, KeyValues const& inputs,
0356 OutKeys const& outputs );
0357
0358
0359 std::string const& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n].key(); }
0360 unsigned int inputLocationSize() const { return m_inputLocations.value().size(); }
0361
0362
0363 StatusCode execute( EventContext const& ) const override final {
0364 vector_of_const_<In> ins;
0365 ins.reserve( m_inputs.size() );
0366 std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ),
0367 details::details2::get_from_handle<In>{} );
0368 try {
0369 return std::apply(
0370 [&]( auto&... outhandle ) {
0371 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
0372 return std::apply(
0373 [&outhandle...]( bool passed, auto&&... data ) {
0374 ( details::put( outhandle, std::forward<decltype( data )>( data ) ), ... );
0375 return passed;
0376 },
0377 ( *this )( std::as_const( ins ) ) );
0378 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0379 },
0380 this->m_outputs )
0381 ? FilterDecision::PASSED
0382 : FilterDecision::FAILED;
0383 } catch ( GaudiException& e ) {
0384 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0385 return e.code();
0386 }
0387 }
0388
0389 virtual std::tuple<bool, Outs...> operator()( const vector_of_const_<In>& inputs ) const = 0;
0390
0391 private:
0392
0393 template <typename T>
0394 using InputHandle_t = details::InputHandle_t<Traits_, typename std::remove_pointer<T>::type>;
0395 std::vector<InputHandle_t<In>> m_inputs;
0396 Gaudi::Property<std::vector<DataObjID>> m_inputLocations;
0397
0398
0399 };
0400
0401 template <typename... Outs, typename In, typename Traits_>
0402 MergingMultiTransformerFilter<std::tuple<Outs...>( const vector_of_const_<In>& ),
0403 Traits_>::MergingMultiTransformerFilter( std::string const& name,
0404 ISvcLocator* pSvcLocator,
0405 KeyValues const& inputs,
0406 OutKeys const& outputs )
0407 : base_class( name, pSvcLocator, outputs )
0408 , m_inputLocations{
0409 this, inputs.first, details::to_DataObjID( inputs.second ),
0410 [this]( Gaudi::Details::PropertyBase& ) {
0411 this->m_inputs = details::make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
0412 if ( std::is_pointer_v<In> ) {
0413
0414
0415 std::for_each( this->m_inputs.begin(), this->m_inputs.end(), []( auto& h ) { h.setOptional( true ); } );
0416 }
0417 },
0418 Gaudi::Details::Property::ImmediatelyInvokeHandler{ true } } {}
0419
0420 }