The Gaudi Framework  v33r0 (d5ea422b)
SplittingTransformer.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 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 #ifndef SPLITTING_TRANSFORMER_H
12 #define SPLITTING_TRANSFORMER_H
13 
14 #include <functional>
15 #include <optional>
16 #include <string>
17 #include <vector>
18 
22 
23 namespace Gaudi::Functional {
24 
25  template <typename Container>
27  template <typename Container>
29 
30  namespace details {
31 
32  template <typename Signature, typename Traits_, bool isLegacy>
34 
36  template <typename Out, typename... In, typename Traits_>
37  class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, true>
38  : public details::DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_> {
39  using base_class = details::DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_>;
40 
41  public:
42  constexpr static std::size_t N = base_class::N_in;
43  using KeyValue = typename base_class::KeyValue;
44  using KeyValues = typename base_class::KeyValues;
45 
47  const KeyValues& outputs )
48  : base_class( name, locator, inputs )
49  , m_outputLocations(
50  this, outputs.first, outputs.second,
51  [=]( Gaudi::Details::PropertyBase& ) {
52  this->m_outputs =
53  details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
54  if constexpr ( details::is_optional_v<Out> ) { // handle constructor does not (yet) allow to
55  // set optional flag... so
56  // do it explicitly here...
57  std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
58  []( auto& h ) { h.setOptional( true ); } );
59  }
60  },
62 
63  SplittingTransformer( const std::string& name, ISvcLocator* locator, const KeyValue& input,
64  const KeyValues& output )
65  : SplittingTransformer( name, locator, std::array<KeyValue, 1>{input}, output ) {
66  static_assert( N == 1, "single input argument requires single input signature" );
67  }
68 
69  // accessor to output Locations
70  const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n]; }
71  unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
72 
73  // derived classes can NOT implement execute
74  StatusCode execute() override final {
75  try {
76  // TODO:FIXME: how does operator() know the number and order of expected outputs?
77  auto out = details::filter_evtcontext_t<In...>::apply( *this, this->m_inputs );
78  if ( out.size() != m_outputs.size() ) {
79  throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
80  " containers, got " + std::to_string( out.size() ) + " instead",
81  this->name(), StatusCode::FAILURE );
82  }
83  for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
85  } catch ( GaudiException& e ) {
86  ( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
87  return e.code();
88  }
89  }
90 
91  // TODO/FIXME: how does the callee know in which order to produce the outputs?
92  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
93  // and only those entries which contain an Out are stored)
94  virtual vector_of_<Out> operator()( const In&... ) const = 0;
95 
96  private:
97  template <typename T>
98  using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
100  Gaudi::Property<std::vector<std::string>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
101  // actual handles!
102  };
103 
104  template <typename Out, typename... In, typename Traits_>
105  class SplittingTransformer<vector_of_<Out>( const In&... ), Traits_, false>
106  : public details::DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_> {
107  using base_class = details::DataHandleMixin<std::tuple<>, std::tuple<In...>, Traits_>;
108 
109  public:
110  constexpr static std::size_t N = base_class::N_in;
111  using KeyValue = typename base_class::KeyValue;
112  using KeyValues = typename base_class::KeyValues;
113 
115  const KeyValues& outputs )
116  : base_class( name, locator, inputs )
117  , m_outputLocations(
118  this, outputs.first, outputs.second,
119  [=]( Gaudi::Details::PropertyBase& ) {
120  this->m_outputs =
121  details::make_vector_of_handles<decltype( this->m_outputs )>( this, m_outputLocations );
122  if constexpr ( details::is_optional_v<Out> ) { // handle constructor does not (yet) allow to
123  // set optional flag... so
124  // do it explicitly here...
125  std::for_each( this->m_outputs.begin(), this->m_outputs.end(),
126  []( auto& h ) { h.setOptional( true ); } );
127  }
128  },
130 
131  SplittingTransformer( const std::string& name, ISvcLocator* locator, const KeyValue& input,
132  const KeyValues& output )
133  : SplittingTransformer( name, locator, std::array<KeyValue, 1>{input}, output ) {
134  static_assert( N == 1, "single input argument requires single input signature" );
135  }
136 
137  // accessor to output Locations
138  const std::string& outputLocation( unsigned int n ) const { return m_outputLocations.value()[n]; }
139  unsigned int outputLocationSize() const { return m_outputLocations.value().size(); }
140 
141  // derived classes can NOT implement execute
142  StatusCode execute( const EventContext& ctx ) const override final {
143  try {
144  // TODO:FIXME: how does operator() know the number and order of expected outputs?
145  auto out = details::filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs );
146  if ( out.size() != m_outputs.size() ) {
147  throw GaudiException( "Error during transform: expected " + std::to_string( m_outputs.size() ) +
148  " containers, got " + std::to_string( out.size() ) + " instead",
149  this->name(), StatusCode::FAILURE );
150  }
151  for ( unsigned i = 0; i != out.size(); ++i ) details::put( m_outputs[i], std::move( out[i] ) );
152  return FilterDecision::PASSED;
153  } catch ( GaudiException& e ) {
154  ( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
155  return e.code();
156  }
157  }
158 
159  // TODO/FIXME: how does the callee know in which order to produce the outputs?
160  // (note: 'missing' items can be specified by making Out an boost::optional<Out>,
161  // and only those entries which contain an Out are stored)
162  virtual vector_of_<Out> operator()( const In&... ) const = 0;
163 
164  private:
165  template <typename T>
166  using OutputHandle = details::OutputHandle_t<Traits_, details::remove_optional_t<T>>;
168  Gaudi::Property<std::vector<std::string>> m_outputLocations; // TODO/FIXME for now: use a call-back to update the
169  // actual handles!
170  };
171 
172  } // namespace details
173 
174  template <typename Signature, typename Traits_ = Traits::useDefaults>
176 
177 } // namespace Gaudi::Functional
178 
179 #endif
Out1 * put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:35
Implementation of property with value of concrete type.
Definition: Property.h:370
SplittingTransformer(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
Gaudi::tagged_bool< class ImmediatelyInvokeHandler_tag > ImmediatelyInvokeHandler
Definition: Property.h:159
T to_string(T... args)
virtual const std::string & message() const
error message to be printed
STL namespace.
This class represents an entry point to all the event specific data.
Definition: EventContext.h:34
SplittingTransformer(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N > &inputs, const KeyValues &outputs)
details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ > base_class
constexpr double second
STL class.
SplittingTransformer(const std::string &name, ISvcLocator *locator, const std::array< KeyValue, N > &inputs, const KeyValues &outputs)
int N
Definition: IOTest.py:110
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
details::template vector_of_const_< Container > vector_of_
T move(T... args)
virtual const StatusCode & code() const
StatusCode for Exception.
SplittingTransformer(const std::string &name, ISvcLocator *locator, const KeyValue &input, const KeyValues &output)
struct GAUDI_API array
Parametrisation class for redirection array - like implementation.
STL class.
STL class.
constexpr static const auto FAILURE
Definition: StatusCode.h:97
details::DataHandleMixin< std::tuple<>, std::tuple< In... >, Traits_ > base_class
Handles make_vector_of_handles(IDataHandleHolder *owner, const std::vector< std::string > &init)
details::OutputHandle_t< Traits_, details::remove_optional_t< T > > OutputHandle
T for_each(T... args)
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202