Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RCustomColumn.hxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Danilo Piparo CERN 09/2018
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_RCUSTOMCOLUMN
12 #define ROOT_RCUSTOMCOLUMN
13 
14 #include "ROOT/RDF/NodesUtils.hxx"
17 #include "ROOT/RDF/Utils.hxx"
19 #include "ROOT/RStringView.hxx"
20 #include "ROOT/TypeTraits.hxx"
21 #include "RtypesCore.h"
22 
23 #include <deque>
24 #include <type_traits>
25 #include <vector>
26 
27 class TTreeReader;
28 
29 namespace ROOT {
30 namespace Detail {
31 namespace RDF {
32 
33 using namespace ROOT::TypeTraits;
34 
35 // clang-format off
36 namespace CustomColExtraArgs {
37 struct None{};
38 struct Slot{};
39 struct SlotAndEntry{};
40 }
41 // clang-format on
42 
43 template <typename F, typename ExtraArgsTag = CustomColExtraArgs::None>
44 class RCustomColumn final : public RCustomColumnBase {
45  // shortcuts
46  using NoneTag = CustomColExtraArgs::None;
47  using SlotTag = CustomColExtraArgs::Slot;
48  using SlotAndEntryTag = CustomColExtraArgs::SlotAndEntry;
49  // other types
50  using FunParamTypes_t = typename CallableTraits<F>::arg_types;
51  using ColumnTypesTmp_t =
52  RDFInternal::RemoveFirstParameterIf_t<std::is_same<ExtraArgsTag, SlotTag>::value, FunParamTypes_t>;
53  using ColumnTypes_t =
54  RDFInternal::RemoveFirstTwoParametersIf_t<std::is_same<ExtraArgsTag, SlotAndEntryTag>::value, ColumnTypesTmp_t>;
55  using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
56  using ret_type = typename CallableTraits<F>::ret_type;
57  // Avoid instantiating vector<bool> as `operator[]` returns temporaries in that case. Use std::deque instead.
58  using ValuesPerSlot_t =
59  typename std::conditional<std::is_same<ret_type, bool>::value, std::deque<ret_type>, std::vector<ret_type>>::type;
60 
61  F fExpression;
62  const ColumnNames_t fColumnNames;
63  ValuesPerSlot_t fLastResults;
64 
65  std::vector<RDFInternal::RDFValueTuple_t<ColumnTypes_t>> fValues;
66 
67  /// The nth flag signals whether the nth input column is a custom column or not.
68  std::array<bool, ColumnTypes_t::list_size> fIsCustomColumn;
69 
70  template <std::size_t... S, typename... BranchTypes>
71  void UpdateHelper(unsigned int slot, Long64_t entry, std::index_sequence<S...>, TypeList<BranchTypes...>, NoneTag)
72  {
73  fLastResults[slot] = fExpression(std::get<S>(fValues[slot]).Get(entry)...);
74  // silence "unused parameter" warnings in gcc
75  (void)slot;
76  (void)entry;
77  }
78 
79  template <std::size_t... S, typename... BranchTypes>
80  void UpdateHelper(unsigned int slot, Long64_t entry, std::index_sequence<S...>, TypeList<BranchTypes...>, SlotTag)
81  {
82  fLastResults[slot] = fExpression(slot, std::get<S>(fValues[slot]).Get(entry)...);
83  // silence "unused parameter" warnings in gcc
84  (void)slot;
85  (void)entry;
86  }
87 
88  template <std::size_t... S, typename... BranchTypes>
89  void
90  UpdateHelper(unsigned int slot, Long64_t entry, std::index_sequence<S...>, TypeList<BranchTypes...>, SlotAndEntryTag)
91  {
92  fLastResults[slot] = fExpression(slot, entry, std::get<S>(fValues[slot]).Get(entry)...);
93  // silence "unused parameter" warnings in gcc
94  (void)slot;
95  (void)entry;
96  }
97 
98 public:
99  RCustomColumn(RLoopManager *lm, std::string_view name, F &&expression, const ColumnNames_t &columns,
100  unsigned int nSlots, const RDFInternal::RBookedCustomColumns &customColumns, bool isDSColumn = false)
101  : RCustomColumnBase(lm, name, nSlots, isDSColumn, customColumns), fExpression(std::forward<F>(expression)),
102  fColumnNames(columns), fLastResults(fNSlots), fValues(fNSlots), fIsCustomColumn()
103  {
104  const auto nColumns = fColumnNames.size();
105  for (auto i = 0u; i < nColumns; ++i)
106  fIsCustomColumn[i] = fCustomColumns.HasName(fColumnNames[i]);
107  }
108 
109  RCustomColumn(const RCustomColumn &) = delete;
110  RCustomColumn &operator=(const RCustomColumn &) = delete;
111 
112  void InitSlot(TTreeReader *r, unsigned int slot) final
113  {
114  if (!fIsInitialized[slot]) {
115  fIsInitialized[slot] = true;
116  RDFInternal::InitRDFValues(slot, fValues[slot], r, fColumnNames, fCustomColumns, TypeInd_t(), fIsCustomColumn);
117  }
118  }
119 
120  void *GetValuePtr(unsigned int slot) final { return static_cast<void *>(&fLastResults[slot]); }
121 
122  void Update(unsigned int slot, Long64_t entry) final
123  {
124  if (entry != fLastCheckedEntry[slot]) {
125  // evaluate this filter, cache the result
126  UpdateHelper(slot, entry, TypeInd_t(), ColumnTypes_t(), ExtraArgsTag{});
127  fLastCheckedEntry[slot] = entry;
128  }
129  }
130 
131  const std::type_info &GetTypeId() const
132  {
133  return fIsDataSourceColumn ? typeid(typename std::remove_pointer<ret_type>::type) : typeid(ret_type);
134  }
135 
136  void ClearValueReaders(unsigned int slot) final
137  {
138  if (fIsInitialized[slot]) {
139  RDFInternal::ResetRDFValueTuple(fValues[slot], TypeInd_t());
140  fIsInitialized[slot] = false;
141  }
142  }
143 };
144 
145 } // ns RDF
146 } // ns Detail
147 } // ns ROOT
148 
149 #endif // ROOT_RCUSTOMCOLUMN