Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 39 additions & 26 deletions Framework/Core/include/Framework/AnalysisTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,25 @@ struct AnalysisDataProcessorBuilder {
(std::get<As>(dest).bindInternalIndicesTo(&std::get<As>(src)), ...);
}

/// The members that binding a process function's arguments can affect.
struct BindableMembers {
template <typename M>
constexpr auto operator()(M& member) const
{
if constexpr (is_partition<M> || is_combinations_generator<M>) {
return std::tuple<M&>{member};
} else {
return std::tuple<>{};
}
}
};

template <typename Members, typename L>
static void forEachRef(Members& members, L&& l)
{
std::apply([&l](auto&... member) { (l(member), ...); }, members);
}

template <typename Task, is_table_iterator_or_enumeration Grouping, std::ranges::input_range R, soa::is_table... Associated>
static void invokeProcess(Task& task, InputRecord& inputs, R matchers, PointerReconstructor const& pointerReconstructor, void (Task::*processingFunction)(Grouping, Associated...), std::vector<ExpressionInfo>& infos, ArrowTableSlicingCache& slices, header::DataOrigin newOrigin = header::DataOrigin{"AOD"})
{
Expand All @@ -326,23 +345,22 @@ struct AnalysisDataProcessorBuilder {
}

constexpr const int numElements = homogeneous_apply_refs_size<false, std::decay_t<Task>>();
auto bindable = apply_refs_tuple_cat_sized<numElements>(BindableMembers{}, task);

// set filtered tables for partitions with grouping
homogeneous_apply_refs_sized<numElements>([&groupingTable](auto& element) {
forEachRef(bindable, [&groupingTable](auto& element) {
analysis_task_parsers::setPartition(element, groupingTable);
analysis_task_parsers::bindInternalIndicesPartition(element, &groupingTable);
return true;
},
task);
});

if constexpr (sizeof...(Associated) == 0) {
// single argument to process
homogeneous_apply_refs_sized<numElements>([&groupingTable](auto& element) {
forEachRef(bindable, [&groupingTable](auto& element) {
analysis_task_parsers::bindExternalIndicesPartition(element, &groupingTable);
analysis_task_parsers::setGroupedCombination(element, groupingTable);
return true;
},
task);
});
if constexpr (soa::is_iterator<G>) {
for (auto& element : groupingTable) {
std::invoke(processingFunction, task, *element);
Expand All @@ -355,13 +373,12 @@ struct AnalysisDataProcessorBuilder {
auto associatedTables = AnalysisDataProcessorBuilder::bindAssociatedTables(inputs, matchers, processingFunction, infos);
// pre-bind self indices
std::apply(
[&task](auto&... t) mutable {
(homogeneous_apply_refs_sized<numElements>(
[&t](auto& p) {
analysis_task_parsers::bindInternalIndicesPartition(p, &t);
return true;
},
task),
[&bindable](auto&... t) mutable {
(forEachRef(bindable,
[&t](auto& p) {
analysis_task_parsers::bindInternalIndicesPartition(p, &t);
return true;
}),
...);
},
associatedTables);
Expand All @@ -370,14 +387,13 @@ struct AnalysisDataProcessorBuilder {
},
associatedTables);

auto binder = [&task, &groupingTable, &associatedTables](auto& x) mutable {
auto binder = [&bindable, &groupingTable, &associatedTables](auto& x) mutable {
x.bindExternalIndices(&groupingTable, &std::get<std::decay_t<Associated>>(associatedTables)...);
homogeneous_apply_refs_sized<numElements>([&x](auto& t) mutable {
forEachRef(bindable, [&x](auto& t) mutable {
analysis_task_parsers::setPartition(t, x);
analysis_task_parsers::bindExternalIndicesPartition(t, &x);
return true;
},
task);
});
};
groupingTable.bindExternalIndices(&std::get<std::decay_t<Associated>>(associatedTables)...);

Expand All @@ -389,11 +405,10 @@ struct AnalysisDataProcessorBuilder {
associatedTables);

// GroupedCombinations bound separately, as they should be set once for all associated tables
homogeneous_apply_refs_sized<numElements>([&groupingTable, &associatedTables](auto& t) {
forEachRef(bindable, [&groupingTable, &associatedTables](auto& t) {
analysis_task_parsers::setGroupedCombination(t, groupingTable, associatedTables);
return true;
},
task);
});
overwriteInternalIndices(associatedTables, associatedTables);
if constexpr (soa::is_iterator<G>) {
auto slicer = GroupSlicer(groupingTable, associatedTables, slices, newOrigin);
Expand All @@ -412,23 +427,21 @@ struct AnalysisDataProcessorBuilder {
associatedSlices);

// bind partitions and grouping table
homogeneous_apply_refs_sized<numElements>([&groupingTable](auto& x) {
forEachRef(bindable, [&groupingTable](auto& x) {
analysis_task_parsers::bindExternalIndicesPartition(x, &groupingTable);
return true;
},
task);
});

[](Task& task, void (Task::*processingFunction)(Grouping, Associated...), Grouping g, std::tuple<std::decay_t<Associated>...>& at) {
std::invoke(processingFunction, task, g, std::get<std::decay_t<Associated>>(at)...);
}(task, processingFunction, slice.groupingElement(), associatedSlices);
}
} else {
// bind partitions and grouping table
homogeneous_apply_refs_sized<numElements>([&groupingTable](auto& x) {
forEachRef(bindable, [&groupingTable](auto& x) {
analysis_task_parsers::bindExternalIndicesPartition(x, &groupingTable);
return true;
},
task);
});

[](Task& task, void (Task::*processingFunction)(Grouping, Associated...), Grouping g, std::tuple<std::decay_t<Associated>...>& at) {
std::invoke(processingFunction, task, g, std::get<std::decay_t<Associated>>(at)...);
Expand Down
100 changes: 63 additions & 37 deletions Framework/Foundation/include/Framework/StructToTuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <Framework/Traits.h>
#include <array>
#include <tuple>

// Structured binding packs (P1061) are C++26, but clang implements them as an
// extension in every language mode and advertises them via the feature test
Expand Down Expand Up @@ -91,11 +92,13 @@ consteval int homogeneous_apply_refs_size()
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++26-extensions"
#endif
template <bool B = false, class T, int D = 0, typename L>
template <bool B = false, class T, int D = 0, typename L, bool Cat = false>
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
auto&& [... members] = object;
if constexpr (sizeof...(members) == 0) {
if constexpr (Cat) {
return std::tuple_cat(l(members)...);
} else if constexpr (sizeof...(members) == 0) {
return std::array<bool, 0>();
} else {
return std::array{l(members)...};
Expand Down Expand Up @@ -155,28 +158,42 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)

#define DPL_FENUM(f, pre, post, d, u) DPL_FENUM_##d##0(f, pre, post), DPL_FENUM_##u(f, pre##d, post)

#define DPL_HOMOGENEOUS_APPLY_ENTRY_LOW(u) \
constexpr(numElements == u) \
{ \
auto&& [DPL_ENUM_##u(p, )] = object; \
return std::array<decltype(l(p0)), u>{DPL_FENUM_##u(l, p, )}; \
#define DPL_HOMOGENEOUS_APPLY_RESULT(n, ...) \
if constexpr (Cat) { \
return std::tuple_cat(__VA_ARGS__); \
} else { \
return std::array<decltype(l(p0)), n>{__VA_ARGS__}; \
}

#define DPL_HOMOGENEOUS_APPLY_ENTRY(d, u) \
constexpr(numElements == d##u) \
{ \
auto&& [DPL_ENUM(p, , d, u)] = object; \
return std::array<decltype(l(p0)), d##u>{DPL_FENUM(l, p, , d, u)}; \
#define DPL_HOMOGENEOUS_APPLY_EMPTY \
if constexpr (Cat) { \
return std::tuple<>(); \
} else { \
return std::array<bool, 0>(); \
}

#define DPL_HOMOGENEOUS_APPLY_ENTRY_TENS(d) \
constexpr(numElements == d##0) \
{ \
auto&& [DPL_ENUM_##d##0(p, )] = object; \
return std::array<decltype(l(p0)), d##0>{DPL_FENUM_##d##0(l, p, )}; \
#define DPL_HOMOGENEOUS_APPLY_ENTRY_LOW(u) \
constexpr(numElements == u) \
{ \
auto&& [DPL_ENUM_##u(p, )] = object; \
DPL_HOMOGENEOUS_APPLY_RESULT(u, DPL_FENUM_##u(l, p, )) \
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
#define DPL_HOMOGENEOUS_APPLY_ENTRY(d, u) \
constexpr(numElements == d##u) \
{ \
auto&& [DPL_ENUM(p, , d, u)] = object; \
DPL_HOMOGENEOUS_APPLY_RESULT(d##u, DPL_FENUM(l, p, , d, u)) \
}

#define DPL_HOMOGENEOUS_APPLY_ENTRY_TENS(d) \
constexpr(numElements == d##0) \
{ \
auto&& [DPL_ENUM_##d##0(p, )] = object; \
DPL_HOMOGENEOUS_APPLY_RESULT(d##0, DPL_FENUM_##d##0(l, p, )) \
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 9)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -192,11 +209,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (9)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 8)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -212,11 +229,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (8)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 7)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -232,11 +249,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (7)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 6)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -252,11 +269,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (6)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 5)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -272,11 +289,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (5)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 4)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -292,11 +309,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (4)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 3)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -312,11 +329,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (3)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 2)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -332,11 +349,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (2)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 1)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -352,11 +369,11 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 1)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_TENS (1)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L, bool Cat = false>
requires(D == 0)
constexpr auto homogeneous_apply_refs(L l, T&& object)
{
Expand All @@ -371,7 +388,7 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_LOW (3)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_LOW (2)
else if DPL_HOMOGENEOUS_APPLY_ENTRY_LOW (1)
else { return std::array<bool,0>(); }
else { DPL_HOMOGENEOUS_APPLY_EMPTY }
// clang-format on
}

Expand All @@ -383,6 +400,15 @@ constexpr auto homogeneous_apply_refs_sized(L l, T&& object)
return homogeneous_apply_refs<false, T, D, L>(l, object);
}

/// Like homogeneous_apply_refs_sized, but l returns a std::tuple for each
/// member and the results are concatenated: returning std::tuple<M&> or
/// std::tuple<>() selects members. The calls to l are unsequenced.
template <int D, typename T, typename L>
constexpr auto apply_refs_tuple_cat_sized(L l, T&& object)
{
return homogeneous_apply_refs<false, T, D, L, true>(l, object);
}

} // namespace o2::framework

#endif // O2_FRAMEWORK_STRUCTTOTUPLE_H_
Loading