Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:07:03

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2023 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #pragma once
0012 
0013 #include "details.h"
0014 #include "utilities.h"
0015 #include <GaudiKernel/FunctionalFilterDecision.h>
0016 #include <GaudiKernel/GaudiException.h>
0017 #include <type_traits>
0018 #include <utility>
0019 
0020 // Adapt an Algorithm (by default, GaudiAlgorithm) so that derived classes
0021 //   a) do not need to access the event store, and have to explicitly
0022 //      state their data dependencies
0023 //   b) are encouraged not to have state which depends on the events
0024 //      (eg. histograms, counters will have to be mutable)
0025 
0026 namespace Gaudi ::Functional {
0027 
0028   namespace details {
0029 
0030     template <typename Signature, typename Traits_, bool isLegacy>
0031     struct Transformer;
0032 
0033     // general N -> 1 algorithms
0034     template <typename Out, typename... In, typename Traits_>
0035     struct Transformer<Out( const In&... ), Traits_, true>
0036         : DataHandleMixin<std::tuple<Out>, filter_evtcontext<In...>, Traits_> {
0037       using DataHandleMixin<std::tuple<Out>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0038 
0039       // derived classes can NOT implement execute
0040       StatusCode execute() override final {
0041         try {
0042           if constexpr ( sizeof...( In ) == 0 ) {
0043             put( std::get<0>( this->m_outputs ), ( *this )() );
0044           } else if constexpr ( std::tuple_size_v<filter_evtcontext<In...>> == 0 ) {
0045             put( std::get<0>( this->m_outputs ), ( *this )( Gaudi::Hive::currentContext() ) );
0046           } else {
0047             put( std::get<0>( this->m_outputs ), filter_evtcontext_t<In...>::apply( *this, this->m_inputs ) );
0048           }
0049           return FilterDecision::PASSED;
0050         } catch ( GaudiException& e ) {
0051           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0052           return e.code();
0053         }
0054       }
0055 
0056       // instead they MUST implement this operator
0057       virtual Out operator()( const In&... ) const = 0;
0058     };
0059 
0060     template <typename Out, typename... In, typename Traits_>
0061     struct Transformer<Out( const In&... ), Traits_, false>
0062         : DataHandleMixin<std::tuple<Out>, filter_evtcontext<In...>, Traits_> {
0063       using DataHandleMixin<std::tuple<Out>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0064 
0065       // derived classes can NOT implement execute
0066       StatusCode execute( const EventContext& ctx ) const override final {
0067         try {
0068           if constexpr ( sizeof...( In ) == 0 ) {
0069             put( std::get<0>( this->m_outputs ), ( *this )() );
0070           } else if constexpr ( std::tuple_size_v<filter_evtcontext<In...>> == 0 ) {
0071             put( std::get<0>( this->m_outputs ), ( *this )( ctx ) );
0072           } else {
0073             put( std::get<0>( this->m_outputs ), filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs ) );
0074           }
0075           return FilterDecision::PASSED;
0076         } catch ( GaudiException& e ) {
0077           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0078           return e.code();
0079         }
0080       }
0081 
0082       // instead they MUST implement this operator
0083       virtual Out operator()( const In&... ) const = 0;
0084     };
0085 
0086     //
0087     // general N -> M algorithms
0088     //
0089     template <typename Signature, typename Traits_, bool isLegacy>
0090     struct MultiTransformer;
0091 
0092     template <typename... Out, typename... In, typename Traits_>
0093     struct MultiTransformer<std::tuple<Out...>( const In&... ), Traits_, true>
0094         : DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_> {
0095       using DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0096 
0097       // derived classes can NOT implement execute
0098       StatusCode execute() override final {
0099         try {
0100           std::apply(
0101               [this]( auto&... ohandle ) {
0102                 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
0103 
0104                 if constexpr ( sizeof...( In ) == 0 ) {
0105                   std::apply( [&ohandle...](
0106                                   auto&&... data ) { ( put( ohandle, std::forward<decltype( data )>( data ) ), ... ); },
0107                               std::as_const( *this )() );
0108                 } else {
0109                   std::apply( [&ohandle...](
0110                                   auto&&... data ) { ( put( ohandle, std::forward<decltype( data )>( data ) ), ... ); },
0111                               filter_evtcontext_t<In...>::apply( std::as_const( *this ), this->m_inputs ) );
0112                 }
0113                 GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0114               },
0115               this->m_outputs );
0116           return FilterDecision::PASSED;
0117         } catch ( GaudiException& e ) {
0118           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0119           return e.code();
0120         }
0121       }
0122 
0123       // instead they MUST implement this operator
0124       virtual std::tuple<Out...> operator()( const In&... ) const = 0;
0125     };
0126 
0127     template <typename... Out, typename... In, typename Traits_>
0128     struct MultiTransformer<std::tuple<Out...>( const In&... ), Traits_, false>
0129         : DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_> {
0130       using DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0131 
0132       // derived classes can NOT implement execute
0133       StatusCode execute( const EventContext& ctx ) const override final {
0134         try {
0135           GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
0136           std::apply(
0137               [this, &ctx]( auto&... ohandle ) {
0138                 if constexpr ( sizeof...( In ) == 0 ) {
0139                   std::apply( [&ohandle...](
0140                                   auto&&... data ) { ( put( ohandle, std::forward<decltype( data )>( data ) ), ... ); },
0141                               ( *this )() );
0142                 } else if constexpr ( std::tuple_size_v<filter_evtcontext<In...>> == 0 ) {
0143                   std::apply( [&ohandle...](
0144                                   auto&&... data ) { ( put( ohandle, std::forward<decltype( data )>( data ) ), ... ); },
0145                               ( *this )( ctx ) );
0146                 } else {
0147                   std::apply( [&ohandle...](
0148                                   auto&&... data ) { ( put( ohandle, std::forward<decltype( data )>( data ) ), ... ); },
0149                               filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs ) );
0150                 }
0151               },
0152               this->m_outputs );
0153           GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0154           return FilterDecision::PASSED;
0155         } catch ( GaudiException& e ) {
0156           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0157           return e.code();
0158         }
0159       }
0160 
0161       // instead they MUST implement this operator
0162       virtual std::tuple<Out...> operator()( const In&... ) const = 0;
0163     };
0164 
0165     //
0166     // general N -> M algorithms with filter functionality
0167     //
0168     template <typename Signature, typename Traits_, bool isLegacy>
0169     struct MultiTransformerFilter;
0170 
0171     template <typename... Out, typename... In, typename Traits_>
0172     struct MultiTransformerFilter<std::tuple<Out...>( const In&... ), Traits_, true>
0173         : DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_> {
0174       using DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0175 
0176       // derived classes can NOT implement execute
0177       StatusCode execute() override final {
0178         try {
0179           return std::apply(
0180                      [&]( auto&... ohandle ) {
0181                        GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN
0182                        return std::apply(
0183                            [&ohandle...]( bool passed, auto&&... data ) {
0184                              ( put( ohandle, std::forward<decltype( data )>( data ) ), ... );
0185                              return passed;
0186                            },
0187                            filter_evtcontext_t<In...>::apply( *this, this->m_inputs ) );
0188                        GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0189                      },
0190                      this->m_outputs )
0191                      ? FilterDecision::PASSED
0192                      : FilterDecision::FAILED;
0193         } catch ( GaudiException& e ) {
0194           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0195           return e.code();
0196         }
0197       }
0198 
0199       // instead they MUST implement this operator
0200       virtual std::tuple<bool, Out...> operator()( const In&... ) const = 0;
0201     };
0202 
0203     template <typename... Out, typename... In, typename Traits_>
0204     struct MultiTransformerFilter<std::tuple<Out...>( const In&... ), Traits_, false>
0205         : DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_> {
0206       using DataHandleMixin<std::tuple<Out...>, filter_evtcontext<In...>, Traits_>::DataHandleMixin;
0207 
0208       // derived classes can NOT implement execute
0209       StatusCode execute( const EventContext& ctx ) const override final {
0210         try {
0211           return std::apply(
0212                      GF_SUPPRESS_SPURIOUS_CLANG_WARNING_BEGIN[&]( auto&... ohandle ) {
0213                        return std::apply(
0214                            [&ohandle...]( bool passed, auto&&... data ) {
0215                              ( put( ohandle, std::forward<decltype( data )>( data ) ), ... );
0216                              return passed;
0217                            },
0218                            filter_evtcontext_t<In...>::apply( *this, ctx, this->m_inputs ) );
0219                      },
0220                      GF_SUPPRESS_SPURIOUS_CLANG_WARNING_END
0221 
0222                      this->m_outputs )
0223                      ? FilterDecision::PASSED
0224                      : FilterDecision::FAILED;
0225         } catch ( GaudiException& e ) {
0226           if ( e.code().isFailure() ) this->error() << e.tag() << " : " << e.message() << endmsg;
0227           return e.code();
0228         }
0229       }
0230 
0231       // instead they MUST implement this operator
0232       virtual std::tuple<bool, Out...> operator()( const In&... ) const = 0;
0233     };
0234   } // namespace details
0235 
0236   template <typename Signature, typename Traits_ = Traits::useDefaults>
0237   using Transformer = details::Transformer<Signature, Traits_, details::isLegacy<Traits_>>;
0238 
0239   template <typename Signature, typename Traits_ = Traits::useDefaults>
0240   using MultiTransformer = details::MultiTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
0241 
0242   template <typename Signature, typename Traits_ = Traits::useDefaults>
0243   using MultiTransformerFilter = details::MultiTransformerFilter<Signature, Traits_, details::isLegacy<Traits_>>;
0244 
0245 } // namespace Gaudi::Functional