Skip to content

Commit dacf735

Browse files
authored
DPL Analysis: refactor inputsFromArgs, update concepts (#13847)
1 parent 0f1ed00 commit dacf735

File tree

2 files changed

+83
-43
lines changed

2 files changed

+83
-43
lines changed

Framework/Core/include/Framework/AnalysisTask.h

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ template <int64_t BEGIN, int64_t END, int64_t STEP>
5959
static constexpr bool is_enumeration_v<Enumeration<BEGIN, END, STEP>> = true;
6060

6161
template <typename T>
62-
concept is_enumeration = is_enumeration_v<T>;
62+
concept is_enumeration = is_enumeration_v<std::decay_t<T>>;
6363

6464
// Helper struct which builds a DataProcessorSpec from
6565
// the contents of an AnalysisTask...
@@ -140,48 +140,84 @@ struct AnalysisDataProcessorBuilder {
140140
DataSpecUtils::updateInputList(inputs, InputSpec{o2::aod::label<R>(), o2::aod::origin<R>(), aod::description(o2::aod::signature<R>()), R.version, Lifetime::Timeframe, inputMetadata});
141141
}
142142

143-
template <typename R, typename C, typename... Args>
144-
static void inputsFromArgs(R (C::*)(Args...), const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos, std::vector<StringPair>& bk, std::vector<StringPair>& bku) requires(std::is_lvalue_reference_v<Args>&&...)
143+
/// helpers to append expression information for a single argument
144+
template <soa::is_table A>
145+
requires(!soa::is_filtered_table<std::decay_t<A>>)
146+
static void addExpression(int, uint32_t, std::vector<ExpressionInfo>&)
145147
{
146-
// update grouping cache
147-
if constexpr (soa::is_iterator<std::decay_t<framework::pack_element_t<0, framework::pack<Args...>>>>) {
148-
addGroupingCandidates<Args...>(bk, bku);
149-
}
148+
}
149+
150+
template <soa::is_filtered_table A>
151+
static void addExpression(int ai, uint32_t hash, std::vector<ExpressionInfo>& eInfos)
152+
{
153+
auto fields = soa::createFieldsFromColumns(typename std::decay_t<A>::persistent_columns_t{});
154+
eInfos.emplace_back(ai, hash, std::decay_t<A>::hashes(), std::make_shared<arrow::Schema>(fields));
155+
}
156+
157+
template <soa::is_iterator A>
158+
static void addExpression(int ai, uint32_t hash, std::vector<ExpressionInfo>& eInfos)
159+
{
160+
addExpression<typename std::decay_t<A>::parent_t>(ai, hash, eInfos);
161+
}
162+
163+
/// helpers to append InputSpec for a single argument
164+
template <soa::is_table A>
165+
static void addInput(const char* name, bool value, std::vector<InputSpec>& inputs)
166+
{
167+
[&name, &value, &inputs]<size_t N, std::array<soa::TableRef, N> refs, size_t... Is>(std::index_sequence<Is...>) mutable {
168+
(addOriginalRef<refs[Is]>(name, value, inputs), ...);
169+
}.template operator()<A::originals.size(), std::decay_t<A>::originals>(std::make_index_sequence<std::decay_t<A>::originals.size()>());
170+
}
171+
172+
template <soa::is_iterator A>
173+
static void addInput(const char* name, bool value, std::vector<InputSpec>& inputs)
174+
{
175+
addInput<typename std::decay_t<A>::parent_t>(name, value, inputs);
176+
}
150177

151-
// populate input list and expression infos
178+
/// helper to append the inputs and expression information for normalized arguments
179+
template <soa::is_table... As>
180+
static void addInputsAndExpressions(uint32_t hash, const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos)
181+
{
152182
int ai = -1;
153-
constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<R (C::*)(Args...)>();
154-
([&name, &value, &eInfos, &inputs, &hash, &ai]() mutable {
183+
([&ai, &hash, &eInfos, &name, &value, &inputs]() mutable {
155184
++ai;
156-
using T = std::decay_t<Args>;
157-
if constexpr (is_enumeration<T>) {
158-
std::vector<ConfigParamSpec> inputMetadata;
159-
// FIXME: for the moment we do not support begin, end and step.
160-
DataSpecUtils::updateInputList(inputs, InputSpec{"enumeration", "DPL", "ENUM", 0, Lifetime::Enumeration, inputMetadata});
161-
} else {
162-
// populate expression infos
163-
if constexpr (soa::is_filtered_table<T>) {
164-
auto fields = soa::createFieldsFromColumns(typename T::persistent_columns_t{});
165-
eInfos.emplace_back(ai, hash, T::hashes(), std::make_shared<arrow::Schema>(fields));
166-
} else if constexpr (soa::is_filtered_iterator<T>) {
167-
auto fields = soa::createFieldsFromColumns(typename T::parent_t::persistent_columns_t{});
168-
eInfos.emplace_back(ai, hash, T::parent_t::hashes(), std::make_shared<arrow::Schema>(fields));
169-
}
170-
// add inputs from the originals
171-
auto adder = [&name, &value, &inputs]<size_t N, std::array<soa::TableRef, N> refs, size_t... Is>(std::index_sequence<Is...>) mutable {
172-
(addOriginalRef<refs[Is]>(name, value, inputs), ...);
173-
};
174-
if constexpr (soa::is_table<T> || soa::is_filtered_table<T>) {
175-
adder.template operator()<T::originals.size(), T::originals>(std::make_index_sequence<T::originals.size()>());
176-
} else if constexpr (soa::is_iterator<T> || soa::is_filtered_iterator<T>) {
177-
adder.template operator()<T::parent_t::originals.size(), T::parent_t::originals>(std::make_index_sequence<T::parent_t::originals.size()>());
178-
}
179-
}
180-
return true;
181-
}() &&
185+
using T = std::decay_t<As>;
186+
addExpression<T>(ai, hash, eInfos);
187+
addInput<T>(name, value, inputs);
188+
}(),
182189
...);
183190
}
184191

192+
/// helper to parse the process arguments
193+
/// 1. enumeration (must be the only argument)
194+
template <typename R, typename C, is_enumeration A>
195+
static void inputsFromArgs(R (C::*)(A), const char* /*name*/, bool /*value*/, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>&, std::vector<StringPair>&, std::vector<StringPair>&)
196+
{
197+
std::vector<ConfigParamSpec> inputMetadata;
198+
// FIXME: for the moment we do not support begin, end and step.
199+
DataSpecUtils::updateInputList(inputs, InputSpec{"enumeration", "DPL", "ENUM", 0, Lifetime::Enumeration, inputMetadata});
200+
}
201+
202+
/// 2. grouping case - 1st argument is an iterator
203+
template <typename R, typename C, soa::is_iterator A, soa::is_table... Args>
204+
static void inputsFromArgs(R (C::*)(A, Args...), const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos, std::vector<StringPair>& bk, std::vector<StringPair>& bku)
205+
requires(std::is_lvalue_reference_v<A> && (std::is_lvalue_reference_v<Args> && ...))
206+
{
207+
addGroupingCandidates<A, Args...>(bk, bku);
208+
constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<R (C::*)(A, Args...)>();
209+
addInputsAndExpressions<typename std::decay_t<A>::parent_t, Args...>(hash, name, value, inputs, eInfos);
210+
}
211+
212+
/// 3. generic case
213+
template <typename R, typename C, soa::is_table... Args>
214+
static void inputsFromArgs(R (C::*)(Args...), const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos, std::vector<StringPair>&, std::vector<StringPair>&)
215+
requires(std::is_lvalue_reference_v<Args> && ...)
216+
{
217+
constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<R (C::*)(Args...)>();
218+
addInputsAndExpressions<Args...>(hash, name, value, inputs, eInfos);
219+
}
220+
185221
template <soa::TableRef R>
186222
static auto extractTableFromRecord(InputRecord& record)
187223
{
@@ -498,19 +534,19 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
498534
homogeneous_apply_refs([&inputs](auto& x) { return ConditionManager<std::decay_t<decltype(x)>>::appendCondition(inputs, x); }, *task.get());
499535

500536
/// parse process functions defined by corresponding configurables
501-
if constexpr (requires { AnalysisDataProcessorBuilder::inputsFromArgs(&T::process, "default", true, inputs, expressionInfos, bindingsKeys, bindingsKeysUnsorted); }) {
537+
if constexpr (requires { &T::process; }) {
502538
AnalysisDataProcessorBuilder::inputsFromArgs(&T::process, "default", true, inputs, expressionInfos, bindingsKeys, bindingsKeysUnsorted);
503539
}
504540
homogeneous_apply_refs(
505-
[name = name_str, &expressionInfos, &inputs, &bindingsKeys, &bindingsKeysUnsorted](auto& x) {
506-
using D = std::decay_t<decltype(x)>;
507-
if constexpr (base_of_template<ProcessConfigurable, D>) {
541+
overloaded{
542+
[name = name_str, &expressionInfos, &inputs, &bindingsKeys, &bindingsKeysUnsorted](framework::is_process_configurable auto& x) mutable {
508543
// this pushes (argumentIndex,processHash,schemaPtr,nullptr) into expressionInfos for arguments that are Filtered/filtered_iterators
509544
AnalysisDataProcessorBuilder::inputsFromArgs(x.process, (name + "/" + x.name).c_str(), x.value, inputs, expressionInfos, bindingsKeys, bindingsKeysUnsorted);
510545
return true;
511-
}
512-
return false;
513-
},
546+
},
547+
[](auto&) {
548+
return false;
549+
}},
514550
*task.get());
515551

516552
// add preslice declarations to slicing cache definition

Framework/Core/include/Framework/Configurable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#ifndef O2_FRAMEWORK_CONFIGURABLE_H_
1212
#define O2_FRAMEWORK_CONFIGURABLE_H_
1313
#include "Framework/ConfigurableKinds.h"
14+
#include "Framework/Traits.h"
1415
#include <string>
1516
#include <vector>
1617
namespace o2::framework
@@ -95,6 +96,9 @@ struct ProcessConfigurable : Configurable<bool, ConfigParamKind::kProcessFlag> {
9596
(As...);
9697
};
9798

99+
template <typename T>
100+
concept is_process_configurable = base_of_template<ProcessConfigurable, T>;
101+
98102
#define PROCESS_SWITCH(_Class_, _Name_, _Help_, _Default_) \
99103
decltype(ProcessConfigurable{&_Class_ ::_Name_, #_Name_, _Default_, _Help_}) do##_Name_ = ProcessConfigurable{&_Class_ ::_Name_, #_Name_, _Default_, _Help_};
100104
#define PROCESS_SWITCH_FULL(_Class_, _Method_, _Name_, _Help_, _Default_) \

0 commit comments

Comments
 (0)