Skip to content

Commit 826a687

Browse files
committed
Added firstIf to chaining task system
1 parent 093212e commit 826a687

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

FWCore/Concurrency/interface/chain_first.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,39 @@ namespace edm {
177177
U f_;
178178
};
179179

180+
template <typename U>
181+
struct WaitingTaskChain<Conditional<U>> {
182+
constexpr explicit WaitingTaskChain(bool iValue, U&& iU) : f_{std::forward<U>(iU)}, conditional_(iValue) {}
183+
184+
[[nodiscard]] WaitingTaskHolder lastTask(WaitingTaskHolder iV) {
185+
if (conditional_) {
186+
return WaitingTaskHolder(
187+
*iV.group(),
188+
make_waiting_task([f = std::move(f_), v = std::move(iV)](const std::exception_ptr* iPtr) mutable {
189+
f(iPtr, std::move(v));
190+
}));
191+
}
192+
return iV;
193+
}
194+
195+
void runLast(WaitingTaskHolder iH) {
196+
if (conditional_) {
197+
f_(nullptr, std::move(iH));
198+
} else {
199+
iH.doneWaiting(std::exception_ptr{});
200+
}
201+
}
202+
203+
template <typename V>
204+
friend auto operator|(WaitingTaskChain<Conditional<U>> iChain, V&& iV) {
205+
return iV.pipe(std::move(iChain));
206+
}
207+
208+
private:
209+
U f_;
210+
bool conditional_;
211+
};
212+
180213
template <typename U, typename... T>
181214
struct WaitingTaskChain<U, T...> {
182215
explicit constexpr WaitingTaskChain(U&& iU, WaitingTaskChain<T...> iL)
@@ -266,6 +299,20 @@ namespace edm {
266299
}
267300
}
268301

302+
/** Sets the first task to be run as part of the task chain, if the value is true, else the following task will be first. The functor is expected to take either
303+
a single argument of type edm::WaitingTaskHolder or two arguments of type std::exception_ptr const* and WaitingTaskHolder. In the latter case, the pointer is only non-null if a previous task in the chain threw an exception.
304+
*/
305+
template <typename F>
306+
[[nodiscard]] constexpr auto firstIf(bool iValue, F&& iF) {
307+
using namespace detail;
308+
if constexpr (has_exception_handling<F>::value) {
309+
return WaitingTaskChain<Conditional<F>>(iValue, std::forward<F>(iF));
310+
} else {
311+
return WaitingTaskChain<Conditional<AutoExceptionHandler<F>>>(iValue,
312+
AutoExceptionHandler<F>(std::forward<F>(iF)));
313+
}
314+
}
315+
269316
/**Define next task to run once this task has finished. Two different functor types are allowed
270317
1. The functor takes a edm::WaitingTaskHolder as argument. If an exception happened in a previous task, the functor will NOT be run.
271318
If an exception happens while running the functor, the exception will be propagated to the WaitingTaskHolder.

FWCore/Concurrency/test/test_catch2_WaitingTaskChain.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,4 +513,47 @@ TEST_CASE("Test chain::first", "[chain::first]") {
513513
REQUIRE(not waitTask.exceptionPtr());
514514
}
515515
}
516+
SECTION("firstIf testing") {
517+
SECTION("firstIf(true) | then | runLast") {
518+
std::atomic<int> count{0};
519+
520+
oneapi::tbb::task_group group;
521+
edm::FinalWaitingTask waitTask{group};
522+
{
523+
using namespace edm::waiting_task::chain;
524+
firstIf(true, [&count](auto h) {
525+
++count;
526+
REQUIRE(count.load() == 1);
527+
}) | then([&count](auto h) {
528+
++count;
529+
REQUIRE(count.load() == 2);
530+
}) | runLast(edm::WaitingTaskHolder(group, &waitTask));
531+
}
532+
waitTask.waitNoThrow();
533+
REQUIRE(count.load() == 2);
534+
REQUIRE(waitTask.done());
535+
REQUIRE(not waitTask.exceptionPtr());
536+
}
537+
538+
SECTION("first(false) | then | runLast") {
539+
std::atomic<int> count{0};
540+
541+
oneapi::tbb::task_group group;
542+
edm::FinalWaitingTask waitTask{group};
543+
{
544+
using namespace edm::waiting_task::chain;
545+
firstIf(false, [&count](auto h) {
546+
++count;
547+
REQUIRE(false);
548+
}) | then([&count](auto h) {
549+
++count;
550+
REQUIRE(count.load() == 1);
551+
}) | runLast(edm::WaitingTaskHolder(group, &waitTask));
552+
}
553+
waitTask.waitNoThrow();
554+
REQUIRE(count.load() == 1);
555+
REQUIRE(waitTask.done());
556+
REQUIRE(not waitTask.exceptionPtr());
557+
}
558+
}
516559
}

0 commit comments

Comments
 (0)