@@ -65,21 +65,18 @@ concept is_enumeration = is_enumeration_v<std::decay_t<T>>;
6565// the contents of an AnalysisTask...
6666namespace {
6767struct AnalysisDataProcessorBuilder {
68- template <typename G, typename... Args>
69- static void addGroupingCandidates(std::vector<StringPair> & bk, std::vector<StringPair> & bku)
68+ template <soa::is_iterator G, typename... Args>
69+ static void addGroupingCandidates(Cache & bk, Cache & bku, bool enabled )
7070 {
71- [&bk, &bku]<typename... As>(framework::pack<As...>) mutable {
72- std::string key;
73- if constexpr (soa::is_iterator<std::decay_t<G>>) {
74- key = std::string{"fIndex"} + o2::framework::cutString(soa::getLabelFromType<std::decay_t<G>>());
75- }
76- ([&bk, &bku, &key]() mutable {
71+ [&bk, &bku, enabled]<typename... As>(framework::pack<As...>) mutable {
72+ auto key = std::string{"fIndex"} + o2::framework::cutString(soa::getLabelFromType<std::decay_t<G>>());
73+ ([&bk, &bku, &key, enabled]() mutable {
7774 if constexpr (soa::relatedByIndex<std::decay_t<G>, std::decay_t<As>>()) {
7875 auto binding = soa::getLabelFromTypeForKey<std::decay_t<As>>(key);
7976 if constexpr (o2::soa::is_smallgroups<std::decay_t<As>>) {
80- framework::updatePairList(bku, binding, key);
77+ framework::updatePairList(bku, binding, key, enabled );
8178 } else {
82- framework::updatePairList(bk, binding, key);
79+ framework::updatePairList(bk, binding, key, enabled );
8380 }
8481 }
8582 }(),
@@ -145,34 +142,72 @@ struct AnalysisDataProcessorBuilder {
145142 }
146143
147144 /// helper to parse the process arguments
145+ template <typename T>
146+ inline static bool requestInputsFromArgs(T&, std::string const&, std::vector<InputSpec>&, std::vector<ExpressionInfo>&)
147+ {
148+ return false;
149+ }
150+ template <is_process_configurable T>
151+ inline static bool requestInputsFromArgs(T& pc, std::string const& name, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eis)
152+ {
153+ AnalysisDataProcessorBuilder::inputsFromArgs(pc.process, (name + "/" + pc.name).c_str(), pc.value, inputs, eis);
154+ return true;
155+ }
156+ template <typename T>
157+ inline static bool requestCacheFromArgs(T&, Cache&, Cache&)
158+ {
159+ return false;
160+ }
161+ template <is_process_configurable T>
162+ inline static bool requestCacheFromArgs(T& pc, Cache& bk, Cache& bku)
163+ {
164+ AnalysisDataProcessorBuilder::cacheFromArgs(pc.process, pc.value, bk, bku);
165+ return true;
166+ }
148167 /// 1. enumeration (must be the only argument)
149168 template <typename R, typename C, is_enumeration A>
150- static void inputsFromArgs(R (C::*)(A), const char* /*name*/, bool /*value*/, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>&, std::vector<StringPair> &, std::vector<StringPair> &)
169+ static void inputsFromArgs(R (C::*)(A), const char* /*name*/, bool /*value*/, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>&) //, Cache &, Cache &)
151170 {
152171 std::vector<ConfigParamSpec> inputMetadata;
153172 // FIXME: for the moment we do not support begin, end and step.
154173 DataSpecUtils::updateInputList(inputs, InputSpec{"enumeration", "DPL", "ENUM", 0, Lifetime::Enumeration, inputMetadata});
155174 }
156175
157- /// 2. grouping case - 1st argument is an iterator
176+ /// 2. 1st argument is an iterator
158177 template <typename R, typename C, soa::is_iterator A, soa::is_table... Args>
159- 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)
178+ static void inputsFromArgs(R (C::*)(A, Args...), const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos) //, Cache & bk, Cache & bku)
160179 requires(std::is_lvalue_reference_v<A> && (std::is_lvalue_reference_v<Args> && ...))
161180 {
162- addGroupingCandidates<A, Args...>(bk, bku);
163181 constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<R (C::*)(A, Args...)>();
164182 addInputsAndExpressions<typename std::decay_t<A>::parent_t, Args...>(hash, name, value, inputs, eInfos);
165183 }
166184
167185 /// 3. generic case
168186 template <typename R, typename C, soa::is_table... Args>
169- 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> &)
187+ static void inputsFromArgs(R (C::*)(Args...), const char* name, bool value, std::vector<InputSpec>& inputs, std::vector<ExpressionInfo>& eInfos) //, Cache &, Cache &)
170188 requires(std::is_lvalue_reference_v<Args> && ...)
171189 {
172190 constexpr auto hash = o2::framework::TypeIdHelpers::uniqueId<R (C::*)(Args...)>();
173191 addInputsAndExpressions<Args...>(hash, name, value, inputs, eInfos);
174192 }
175193
194+ /// 1. enumeration (no grouping)
195+ template <typename R, typename C, is_enumeration A>
196+ static void cacheFromArgs(R (C::*)(A), bool, Cache&, Cache&)
197+ {
198+ }
199+ /// 2. iterator (the only grouping case)
200+ template <typename R, typename C, soa::is_iterator A, soa::is_table... Args>
201+ static void cacheFromArgs(R (C::*)(A, Args...), bool value, Cache& bk, Cache& bku)
202+ {
203+ addGroupingCandidates<A, Args...>(bk, bku, value);
204+ }
205+ /// 3. generic case (no grouping)
206+ template <typename R, typename C, soa::is_table A, soa::is_table... Args>
207+ static void cacheFromArgs(R (C::*)(A, Args...), bool, Cache&, Cache&)
208+ {
209+ }
210+
176211 template <soa::TableRef R>
177212 static auto extractTableFromRecord(InputRecord& record)
178213 {
@@ -480,8 +515,6 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
480515 std::vector<InputSpec> inputs;
481516 std::vector<ConfigParamSpec> options;
482517 std::vector<ExpressionInfo> expressionInfos;
483- std::vector<StringPair> bindingsKeys;
484- std::vector<StringPair> bindingsKeysUnsorted;
485518
486519 /// make sure options and configurables are set before expression infos are created
487520 homogeneous_apply_refs([&options, &hash](auto& element) { return analysis_task_parsers::appendOption(options, element); }, *task.get());
@@ -490,23 +523,15 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
490523
491524 /// parse process functions defined by corresponding configurables
492525 if constexpr (requires { &T::process; }) {
493- AnalysisDataProcessorBuilder::inputsFromArgs(&T::process, "default", true, inputs, expressionInfos, bindingsKeys, bindingsKeysUnsorted );
526+ AnalysisDataProcessorBuilder::inputsFromArgs(&T::process, "default", true, inputs, expressionInfos);
494527 }
495528 homogeneous_apply_refs(
496- overloaded{
497- [name = name_str, &expressionInfos, &inputs, &bindingsKeys, &bindingsKeysUnsorted](framework::is_process_configurable auto& x) mutable {
498- // this pushes (argumentIndex,processHash,schemaPtr,nullptr) into expressionInfos for arguments that are Filtered/filtered_iterators
499- AnalysisDataProcessorBuilder::inputsFromArgs(x.process, (name + "/" + x.name).c_str(), x.value, inputs, expressionInfos, bindingsKeys, bindingsKeysUnsorted);
500- return true;
501- },
502- [](auto&) {
503- return false;
504- }},
529+ [name = name_str, &expressionInfos, &inputs](auto& x) mutable {
530+ // this pushes (argumentIndex, processHash, schemaPtr, nullptr) into expressionInfos for arguments that are Filtered/filtered_iterators
531+ return AnalysisDataProcessorBuilder::requestInputsFromArgs(x, name, inputs, expressionInfos);
532+ },
505533 *task.get());
506534
507- // add preslice declarations to slicing cache definition
508- homogeneous_apply_refs([&bindingsKeys, &bindingsKeysUnsorted](auto& element) { return analysis_task_parsers::registerCache(element, bindingsKeys, bindingsKeysUnsorted); }, *task.get());
509-
510535 // request base tables for spawnable extended tables and indices to be built
511536 // this checks for duplications
512537 homogeneous_apply_refs([&inputs](auto& element) {
@@ -526,7 +551,12 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
526551 requiredServices.insert(requiredServices.end(), arrowServices.begin(), arrowServices.end());
527552 homogeneous_apply_refs([&requiredServices](auto& element) { return analysis_task_parsers::addService(requiredServices, element); }, *task.get());
528553
529- auto algo = AlgorithmSpec::InitCallback{[task = task, expressionInfos, bindingsKeys, bindingsKeysUnsorted](InitContext& ic) mutable {
554+ auto algo = AlgorithmSpec::InitCallback{[task = task, expressionInfos](InitContext& ic) mutable {
555+ Cache bindingsKeys;
556+ Cache bindingsKeysUnsorted;
557+ // add preslice declarations to slicing cache definition
558+ homogeneous_apply_refs([&bindingsKeys, &bindingsKeysUnsorted](auto& element) { return analysis_task_parsers::registerCache(element, bindingsKeys, bindingsKeysUnsorted); }, *task.get());
559+
530560 homogeneous_apply_refs([&ic](auto&& element) { return analysis_task_parsers::prepareOption(ic, element); }, *task.get());
531561 homogeneous_apply_refs([&ic](auto&& element) { return analysis_task_parsers::prepareService(ic, element); }, *task.get());
532562
@@ -556,6 +586,16 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args)
556586 task->init(ic);
557587 }
558588
589+ /// parse process functions to enable requested grouping caches - note that at this state process configurables have their final values
590+ if constexpr (requires { &T::process; }) {
591+ AnalysisDataProcessorBuilder::cacheFromArgs(&T::process, true, bindingsKeys, bindingsKeysUnsorted);
592+ }
593+ homogeneous_apply_refs(
594+ [&bindingsKeys, &bindingsKeysUnsorted](auto& x) mutable {
595+ return AnalysisDataProcessorBuilder::requestCacheFromArgs(x, bindingsKeys, bindingsKeysUnsorted);
596+ },
597+ *task.get());
598+
559599 ic.services().get<ArrowTableSlicingCacheDef>().setCaches(std::move(bindingsKeys));
560600 ic.services().get<ArrowTableSlicingCacheDef>().setCachesUnsorted(std::move(bindingsKeysUnsorted));
561601 // initialize global caches
0 commit comments