The Gaudi Framework  master (34daa81a)
Loading...
Searching...
No Matches
MergingTransformer.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#pragma once
12
13#include "details.h"
14#include "utilities.h"
15#include <Gaudi/Algorithm.h>
17#include <functional>
18#include <string>
19#include <vector>
20
21namespace Gaudi::Functional {
22
24
25 namespace details {
26 template <typename F, size_t... Is>
27 auto for_impl( F&& f, std::index_sequence<Is...> ) {
28 if constexpr ( std::disjunction_v<std::is_void<std::invoke_result_t<F, std::integral_constant<int, Is>>>...> ) {
29 ( std::invoke( f, std::integral_constant<int, Is>{} ), ... );
30 } else {
31 return std::array{ std::invoke( f, std::integral_constant<int, Is>{} )... };
32 }
33 }
34
35 template <auto N, typename F>
36 decltype( auto ) for_( F&& f ) {
37 return for_impl( std::forward<F>( f ), std::make_index_sequence<N>{} );
38 }
39
40 template <typename Sig>
41 constexpr bool is_void_fun_v = false;
42 template <typename... Args>
43 constexpr bool is_void_fun_v<void( Args... )> = true;
44 template <typename Sig>
46
47 template <typename Signature, typename Traits_, bool isLegacy>
49
51 template <typename Out, typename In, typename Traits_>
52 struct MergingTransformer<Out( const vector_of_const_<In>& ), Traits_, true>
53 : DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_> {
54 private:
55 using base_class = DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_>;
56
57 public:
58 using KeyValue = typename base_class::KeyValue;
59 using KeyValues = typename base_class::KeyValues;
60
61 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
62 : base_class( std::move( name ), locator )
63 , m_inputLocations{ this, inputs.first, details::to_DataObjID( inputs.second ),
64 [this]( Gaudi::Details::PropertyBase& ) {
65 this->m_inputs =
66 make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
67 },
69 static_assert( std::is_void_v<Out> );
70 }
71
72 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
73 : base_class( std::move( name ), locator, output )
74 , m_inputLocations{ this, inputs.first, details::to_DataObjID( inputs.second ),
75 [this]( Gaudi::Details::PropertyBase& ) {
76 this->m_inputs =
77 make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
78 },
80 static_assert( !std::is_void_v<Out> );
81 }
82
83 // accessor to input Locations
84 const std::string& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n].key(); }
85 unsigned int inputLocationSize() const { return m_inputLocations.value().size(); }
86
87 // derived classes can NOT implement execute
88 StatusCode execute() override final {
90 ins.reserve( m_inputs.size() );
91 std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ), details2::get_from_handle<In>{} );
92 try {
93 if constexpr ( std::is_void_v<Out> ) {
94 std::as_const ( *this )( std::as_const( ins ) );
95 } else {
96 put( std::get<0>( this->m_outputs ), std::as_const( *this )( std::as_const( ins ) ) );
97 }
99 } catch ( GaudiException& e ) {
100 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
101 return e.code();
102 }
103 }
104
105 virtual Out operator()( const vector_of_const_<In>& inputs ) const = 0;
106
107 private:
108 // if In is a pointer, it signals optional (as opposed to mandatory) input
109 template <typename T>
111 std::vector<InputHandle_t<In>> m_inputs; // and make the handles properties instead...
112 Gaudi::Property<std::vector<DataObjID>> m_inputLocations; // TODO/FIXME: remove this duplication...
113 // TODO/FIXME: replace vector of DataObjID property + call-back with a
114 // vector<handle> property ... as soon as declareProperty can deal with that.
115 };
116
117 template <typename Out, typename... Ins, typename Traits_>
118 struct MergingTransformer<Out( const vector_of_const_<Ins>&... ), Traits_, false>
119 : DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_> {
120
121 using base_class = DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_>;
122 using KeyValue = typename base_class::KeyValue;
123 using KeyValues = typename base_class::KeyValues;
124 using InKeys = details::RepeatValues_<KeyValues, sizeof...( Ins )>;
125
126 private:
128 return details::for_<sizeof...( Ins )>( [&]( auto I ) {
129 constexpr auto i = decltype( I )::value;
130 auto& ins = std::get<i>( inputs );
131 return Gaudi::Property<std::vector<DataObjID>>{ this, ins.first, details::to_DataObjID( ins.second ),
132 [this]( auto&& ) {
133 auto& handles = std::get<i>( this->m_inputs );
134 auto& ins = std::get<i>( this->m_inputLocations );
135 using Handles = typename std::decay_t<decltype( handles )>;
136 handles = make_vector_of_handles<Handles>( this, ins );
137 },
139 } );
140 }
141
142 public:
143 MergingTransformer( std::string name, ISvcLocator* locator, InKeys inputs )
144 : base_class( std::move( name ), locator ), m_inputLocations{ construct_properties( inputs ) } {
145 static_assert( std::is_void_v<Out> );
146 }
147
148 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
149 : MergingTransformer{ std::move( name ), locator, InKeys{ inputs } } {
150 static_assert( sizeof...( Ins ) == 1 );
151 }
152
153 MergingTransformer( std::string name, ISvcLocator* locator, InKeys inputs, const KeyValue& output )
154 : base_class( std::move( name ), locator, output ), m_inputLocations{ construct_properties( inputs ) } {
155 static_assert( !std::is_void_v<Out> );
156 }
157
158 MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
159 : MergingTransformer{ std::move( name ), locator, InKeys{ inputs }, output } {
160 static_assert( sizeof...( Ins ) == 1 );
161 }
162
163 // accessor to input Locations
164 const std::string& inputLocation( unsigned int i, unsigned int j ) const {
165 return m_inputLocations.at( i ).value().at( j ).key();
166 }
167 const std::string& inputLocation( unsigned int i ) const {
168 static_assert( sizeof...( Ins ) == 1 );
169 return inputLocation( 0, i );
170 }
171 unsigned int inputLocationSize( int i = 0 ) const { return m_inputLocations.at( i ).value().size(); }
172
173 // derived classes can NOT implement execute
174 StatusCode execute( const EventContext& ) const override final {
175 std::tuple<vector_of_const_<Ins>...> inss;
176 details::for_<sizeof...( Ins )>( [&]( auto I ) {
177 constexpr size_t i = decltype( I )::value;
178 auto& ins = std::get<i>( inss );
179 auto& handles = std::get<i>( m_inputs );
180 ins.reserve( handles.size() );
181 std::transform( handles.begin(), handles.end(), std::back_inserter( ins ),
182 details::details2::get_from_handle<typename std::decay_t<decltype( ins )>::value_type>{} );
183 } );
184 try {
185 if constexpr ( std::is_void_v<Out> ) {
186 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); }, inss );
187 } else {
188 put( std::get<0>( this->m_outputs ),
189 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); },
190 inss ) );
191 }
193 } catch ( GaudiException& e ) {
194 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
195 return e.code();
196 }
197 }
198
199 virtual Out operator()( const vector_of_const_<Ins>&... inputs ) const = 0;
200
201 private:
202 // if In is a pointer, it signals optional (as opposed to mandatory) input
203 template <typename T>
205 std::tuple<std::vector<InputHandle_t<Ins>>...> m_inputs; // and make the handles properties instead...
206 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...( Ins )> m_inputLocations; // TODO/FIXME: remove
207 // this duplication...
208 // TODO/FIXME: replace vector of string property + call-back with a
209 // vector<handle> property ... as soon as declareProperty can deal with that.
210 };
211
212 } // namespace details
213
214 template <typename Signature, typename Traits_ = Traits::useDefaults>
216
217 // more meaningful alias for cases where the return type in Signature is void
218 template <details::is_void_fun Signature, typename Traits_ = Traits::useDefaults>
220
221 // M vectors of the same -> N
222 template <typename Signature, typename Traits_ = Traits::BaseClass_t<Gaudi::Algorithm>>
224
225 template <typename... Outs, typename... Ins, typename Traits_>
226 struct MergingMultiTransformer<std::tuple<Outs...>( vector_of_const_<Ins> const&... ), Traits_>
227 : details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_> {
228
229 private:
230 using base_class = details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_>;
231
232 public:
233 using KeyValue = typename base_class::KeyValue;
234 using KeyValues = typename base_class::KeyValues;
235 using InKeys = details::RepeatValues_<KeyValues, sizeof...( Ins )>;
236 using OutKeys = details::RepeatValues_<KeyValue, sizeof...( Outs )>;
237 static constexpr size_t n_args = sizeof...( Ins );
238
239 MergingMultiTransformer( std::string const& name, ISvcLocator* pSvcLocator, InKeys inputs, OutKeys outputs )
240 : base_class{ name, pSvcLocator, std::move( outputs ) }
241 , m_inputLocations{ details::for_<n_args>( [&]( auto I ) {
242 constexpr auto i = decltype( I )::value;
243 auto& ins = std::get<i>( inputs );
245 this, ins.first, details::to_DataObjID( ins.second ),
246 [this]( auto&& ) {
247 auto& handles = std::get<i>( this->m_inputs );
248 auto& ins = std::get<i>( this->m_inputLocations );
249 handles = details::make_vector_of_handles<std::decay_t<decltype( handles )>>( this, ins );
250 },
252 } ) } {}
253
254 MergingMultiTransformer( std::string const& name, ISvcLocator* pSvcLocator, KeyValues inputs, OutKeys outputs )
255 : MergingMultiTransformer{ name, pSvcLocator, InKeys{ std::move( inputs ) }, std::move( outputs ) } {
256 static_assert( sizeof...( Ins ) == 1 );
257 }
258
259 // accessor to input Locations
260 std::string const& inputLocation( unsigned int i, unsigned int j ) const {
261 return m_inputLocations.at( i ).value().at( j ).key();
262 }
263 std::string const& inputLocation( unsigned int j ) const {
264 static_assert( n_args == 1 );
265 return inputLocation( 0, j );
266 }
267 unsigned int inputLocationSize( int i = 0 ) const { return m_inputLocations.at( i ).value().size(); }
268
269 // derived classes can NOT implement execute
270 StatusCode execute( EventContext const& ) const override final {
271 std::tuple<vector_of_const_<Ins>...> inss;
272 details::for_<sizeof...( Ins )>( [&]( auto I ) {
273 constexpr size_t i = decltype( I )::value;
274 auto& ins = std::get<i>( inss );
275 auto& handles = std::get<i>( m_inputs );
276 ins.reserve( handles.size() );
277 std::transform( handles.begin(), handles.end(), std::back_inserter( ins ),
278 details::details2::get_from_handle<typename std::decay_t<decltype( ins )>::value_type>{} );
279 } );
280 try {
281 std::apply(
282 [&]( auto&... outhandle ) {
283 std::apply(
284 [&outhandle...]( auto&&... data ) {
285 ( details::put( outhandle, std::forward<decltype( data )>( data ) ), ... );
286 },
287 std::apply( [&]( auto&&... ins ) { return std::as_const( *this )( std::as_const( ins )... ); },
288 inss ) );
289 },
290 this->m_outputs );
292 } catch ( GaudiException& e ) {
293 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
294 return e.code();
295 }
296 }
297
298 virtual std::tuple<Outs...> operator()( const vector_of_const_<Ins>&... inputs ) const = 0;
299
300 private:
301 // if In is a pointer, it signals optional (as opposed to mandatory) input
302 template <typename T>
304 std::tuple<std::vector<InputHandle_t<Ins>>...> m_inputs; // and make the handles properties instead...
305 std::array<Gaudi::Property<std::vector<DataObjID>>, sizeof...( Ins )> m_inputLocations; // TODO/FIXME: remove this
306 // duplication...
307 // TODO/FIXME: replace vector of string property + call-back with a
308 // vector<handle> property ... as soon as declareProperty can deal with that.
309 };
310
311 // Many of the same -> N with filter functionality
312 template <typename Signature, typename Traits_ = Traits::BaseClass_t<Gaudi::Algorithm>>
314
315 template <typename... Outs, typename In, typename Traits_>
316 struct MergingMultiTransformerFilter<std::tuple<Outs...>( vector_of_const_<In> const& ), Traits_>
317 : details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_> {
318
319 private:
320 using base_class = details::DataHandleMixin<std::tuple<Outs...>, std::tuple<>, Traits_>;
321
322 public:
323 using KeyValue = typename base_class::KeyValue;
324 using KeyValues = typename base_class::KeyValues;
325 using OutKeys = details::RepeatValues_<KeyValue, sizeof...( Outs )>;
326
327 MergingMultiTransformerFilter( std::string const& name, ISvcLocator* locator, KeyValues const& inputs,
328 OutKeys const& outputs );
329
330 // accessor to input Locations
331 std::string const& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n].key(); }
332 unsigned int inputLocationSize() const { return m_inputLocations.value().size(); }
333
334 // derived classes can NOT implement execute
335 StatusCode execute( EventContext const& ) const override final {
337 ins.reserve( m_inputs.size() );
338 std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ),
340 try {
341 return std::apply(
342 [&]( auto&... outhandle ) {
343 return std::apply(
344 [&outhandle...]( bool passed, auto&&... data ) {
345 ( details::put( outhandle, std::forward<decltype( data )>( data ) ), ... );
346 return passed;
347 },
348 ( *this )( std::as_const( ins ) ) );
349 },
350 this->m_outputs )
353 } catch ( GaudiException& e ) {
354 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
355 return e.code();
356 }
357 }
358
359 virtual std::tuple<bool, Outs...> operator()( const vector_of_const_<In>& inputs ) const = 0;
360
361 private:
362 // if In is a pointer, it signals optional (as opposed to mandatory) input
363 template <typename T>
365 std::vector<InputHandle_t<In>> m_inputs; // and make the handles properties instead...
366 Gaudi::Property<std::vector<DataObjID>> m_inputLocations; // TODO/FIXME: remove this duplication...
367 // TODO/FIXME: replace vector of string property + call-back with a
368 // vector<handle> property ... as soon as declareProperty can deal with that.
369 };
370
371 template <typename... Outs, typename In, typename Traits_>
372 MergingMultiTransformerFilter<std::tuple<Outs...>( const vector_of_const_<In>& ),
373 Traits_>::MergingMultiTransformerFilter( std::string const& name,
374 ISvcLocator* pSvcLocator,
375 KeyValues const& inputs,
376 OutKeys const& outputs )
377 : base_class( name, pSvcLocator, outputs )
378 , m_inputLocations{ this, inputs.first, details::to_DataObjID( inputs.second ),
380 this->m_inputs =
381 details::make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
382 },
384
385} // namespace Gaudi::Functional
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
This class represents an entry point to all the event specific data.
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
Define general base for Gaudi exception.
virtual const std::string & message() const
error message to be printed
virtual const StatusCode & code() const
StatusCode for Exception.
virtual const std::string & tag() const
name tag for the exception, or exception type
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
Gaudi::tagged_bool< class ImmediatelyInvokeHandler_tag > ImmediatelyInvokeHandler
Definition Property.h:23
std::vector< DataObjID > to_DataObjID(const std::vector< std::string > &in)
Definition details.h:106
decltype(auto) for_(F &&f)
typename detail2::InputHandle< T, Tr, detail2::DefaultInputHandle >::type InputHandle_t
Definition details.h:458
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition details.h:162
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< DataObjID > &init)
Definition details.h:467
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
Definition details.h:158
auto for_impl(F &&f, std::index_sequence< Is... >)
details::MergingTransformer< Signature, Traits_, details::isLegacy< Traits_ > > MergingTransformer
details::MergingTransformer< Signature, Traits_, details::isLegacy< Traits_ > > MergingConsumer
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1
STL namespace.
virtual std::tuple< bool, Outs... > operator()(const vector_of_const_< In > &inputs) const =0
MergingMultiTransformerFilter(std::string const &name, ISvcLocator *locator, KeyValues const &inputs, OutKeys const &outputs)
MergingMultiTransformer(std::string const &name, ISvcLocator *pSvcLocator, KeyValues inputs, OutKeys outputs)
virtual std::tuple< Outs... > operator()(const vector_of_const_< Ins > &... inputs) const =0
MergingMultiTransformer(std::string const &name, ISvcLocator *pSvcLocator, InKeys inputs, OutKeys outputs)
std::array< Gaudi::Property< std::vector< DataObjID > >, sizeof...(Ins)> m_inputLocations
MergingTransformer(std::string name, ISvcLocator *locator, InKeys inputs, const KeyValue &output)
MergingTransformer(std::string name, ISvcLocator *locator, const KeyValues &inputs, const KeyValue &output)
MergingTransformer(std::string name, ISvcLocator *locator, const KeyValues &inputs, const KeyValue &output)