The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
SplittingTransformer.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 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"
16#include <functional>
17#include <optional>
18#include <string>
19#include <vector>
20
21namespace Gaudi::Functional {
22
23 template <typename Container>
24 using vector_of_ = std::vector<Container>;
25 template <typename Container>
26 using vector_of_optional_ = std::vector<std::optional<Container>>;
27
28 namespace details {
29
30 template <typename Signature, typename Traits_, bool isLegacy>
32
34 template <typename Out, typename... In, typename Traits_>
35 class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, true>
36 : public details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_> {
38
39 public:
40 constexpr static std::size_t N = base_class::N_in;
41 using KeyValue = typename base_class::KeyValue;
42 using KeyValues = typename base_class::KeyValues;
43
44 SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_<KeyValue, N>& inputs,
45 const KeyValues& outputs )
46 : base_class( std::move( name ), locator, inputs )
48 this, outputs.first, details::to_DataObjID( outputs.second ),
49 [this]( Gaudi::Details::PropertyBase& ) {
50 this->m_outputs =
52 if constexpr ( details::is_optional<Out> ) { // handle constructor does not (yet) allow to
53 // set optional flag... so
54 // do it explicitly here...
55 std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
56 []( auto& h ) { h.setOptional( true ); } );
57 }
58 },
60
61 SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output )
62 : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) {
63 static_assert( N == 1, "single input argument requires single input signature" );
64 }
65
66 // accessor to output Locations
67 const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n].key(); }
68 unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
69
70 // derived classes can NOT implement execute
71 StatusCode execute() override final {
72 try {
73 // TODO:FIXME: how does operator() know the number and order of expected outputs?
74 auto out = details::filter_evtcontext_t<In...>::apply( *this, this->m_inputs );
75 if ( out.size() != m_outputs.size() ) {
76 throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
77 " containers, got " + std::to_string( out.size() ) + " instead",
78 this->name(), StatusCode::FAILURE );
79 }
80 for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
82 } catch ( GaudiException& e ) {
83 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
84 return e.code();
85 }
86 }
87
88 // TODO/FIXME: how does the callee know in which order to produce the outputs?
89 // (note: 'missing' items can be specified by making Out an std::optional<Out>,
90 // and only those entries which contain an Out are stored)
91 virtual vector_of_<Out> operator()( const In&... ) const = 0;
92
93 private:
94 template <typename T>
96 std::vector<OutputHandle<Out>> m_outputs;
97 Gaudi::Property<std::vector<DataObjID>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
98 // actual handles!
99 };
100
101 template <typename Out, typename... In, typename Traits_>
102 class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, false>
103 : public details::DataHandleMixin<std::tuple<>, filter_evtcontext<In...>, Traits_> {
105
106 public:
107 constexpr static std::size_t N = base_class::N_in;
108 using KeyValue = typename base_class::KeyValue;
109 using KeyValues = typename base_class::KeyValues;
110
111 SplittingTransformer( std::string name, ISvcLocator* locator, const RepeatValues_<KeyValue, N>& inputs,
112 const KeyValues& outputs )
113 : base_class( std::move( name ), locator, inputs )
115 this, outputs.first, details::to_DataObjID( outputs.second ),
116 [this]( Gaudi::Details::PropertyBase& ) {
117 this->m_outputs =
119 if constexpr ( details::is_optional<Out> ) { // handle constructor does not (yet) allow to
120 // set optional flag... so
121 // do it explicitly here...
122 std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
123 []( auto& h ) { h.setOptional( true ); } );
124 }
125 },
127
128 SplittingTransformer( std::string name, ISvcLocator* locator, const KeyValue& input, const KeyValues& output )
129 : SplittingTransformer( std::move( name ), locator, std::forward_as_tuple( input ), output ) {
130 static_assert( N == 1, "single input argument requires single input signature" );
131 }
132
133 // accessor to output Locations
134 const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n].key(); }
135 unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
136
137 // derived classes can NOT implement execute
138 StatusCode execute( const EventContext& ctx ) const override final {
139 try {
140 // TODO:FIXME: how does operator() know the number and order of expected outputs?
141 auto out = details::filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs );
142 if ( out.size() != m_outputs.size() ) {
143 throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
144 " containers, got " + std::to_string( out.size() ) + " instead",
145 this->name(), StatusCode::FAILURE );
146 }
147 for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
149 } catch ( GaudiException& e ) {
150 if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
151 return e.code();
152 }
153 }
154
155 // TODO/FIXME: how does the callee know in which order to produce the outputs?
156 // (note: 'missing' items can be specified by making Out an std::optional<Out>,
157 // and only those entries which contain an Out are stored)
158 virtual vector_of_<Out> operator()( const In&... ) const = 0;
159
160 private:
161 template <typename T>
163 std::vector<OutputHandle<Out>> m_outputs;
164 Gaudi::Property<std::vector<DataObjID>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
165 // actual handles!
166 };
167
168 } // namespace details
169
170 template <typename Signature, typename Traits_ = Traits::useDefaults>
172
173} // 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.
SplittingTransformer(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
SplittingTransformer(std::string name, ISvcLocator *locator, const RepeatValues_< KeyValue, N > &inputs, const KeyValues &outputs)
details::DataHandleMixin< std::tuple<>, filter_evtcontext< In... >, Traits_ > base_class
SplittingTransformer(std::string name, ISvcLocator *locator, const RepeatValues_< KeyValue, N > &inputs, const KeyValues &outputs)
details::DataHandleMixin< std::tuple<>, filter_evtcontext< In... >, Traits_ > base_class
SplittingTransformer(std::string name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
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
constexpr static const auto FAILURE
Definition StatusCode.h:100
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
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
typename detail2::OutputHandle< T, Tr, DataObjectWriteHandle >::type OutputHandle_t
Definition details.h:455
decltype(get_values_helper< Value >(std::make_index_sequence< N >())) RepeatValues_
Definition details.h:158
typename filter_evtcontext_t< In... >::type filter_evtcontext
Definition details.h:534
std::vector< Container > vector_of_
std::vector< std::optional< Container > > vector_of_optional_
details::SplittingTransformer< Signature, Traits_, details::isLegacy< Traits_ > > SplittingTransformer
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.
static auto apply(const Algorithm &algo, const EventContext &ctx, Handles &handles)
Definition details.h:504