File indexing completed on 2024-04-06 12:11:56
0001
0002
0003
0004
0005
0006
0007
0008 #define CATCH_CONFIG_MAIN
0009 #include "catch.hpp"
0010
0011 #include "oneapi/tbb/global_control.h"
0012
0013 #include "FWCore/Concurrency/interface/chain_first.h"
0014 #include "FWCore/Concurrency/interface/FinalWaitingTask.h"
0015
0016 TEST_CASE("Test chain::first", "[chain::first]") {
0017 oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, 1);
0018
0019 SECTION("no explicit exception handling") {
0020 SECTION("first | lastTask") {
0021 std::atomic<int> count{0};
0022
0023 oneapi::tbb::task_group group;
0024 edm::FinalWaitingTask waitTask{group};
0025 {
0026 using namespace edm::waiting_task::chain;
0027 auto h = first([&count](edm::WaitingTaskHolder h) {
0028 ++count;
0029 REQUIRE(count.load() == 1);
0030 }) |
0031 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0032
0033 h.doneWaiting(std::exception_ptr());
0034 }
0035 waitTask.waitNoThrow();
0036 REQUIRE(count.load() == 1);
0037 REQUIRE(waitTask.done());
0038 REQUIRE(not waitTask.exceptionPtr());
0039 }
0040
0041 SECTION("first | then | lastTask") {
0042 std::atomic<int> count{0};
0043
0044 oneapi::tbb::task_group group;
0045 edm::FinalWaitingTask waitTask{group};
0046 {
0047 using namespace edm::waiting_task::chain;
0048 auto h = first([&count](auto h) {
0049 ++count;
0050 REQUIRE(count.load() == 1);
0051 }) |
0052 then([&count](auto h) {
0053 ++count;
0054 REQUIRE(count.load() == 2);
0055 }) |
0056 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0057
0058 h.doneWaiting(std::exception_ptr());
0059 }
0060 waitTask.waitNoThrow();
0061 REQUIRE(count.load() == 2);
0062 REQUIRE(waitTask.done());
0063 REQUIRE(not waitTask.exceptionPtr());
0064 }
0065
0066 SECTION("first | then | then | lastTask") {
0067 std::atomic<int> count{0};
0068
0069 oneapi::tbb::task_group group;
0070 edm::FinalWaitingTask waitTask{group};
0071 {
0072 using namespace edm::waiting_task::chain;
0073 auto h = first([&count](auto h) {
0074 ++count;
0075 REQUIRE(count.load() == 1);
0076 }) |
0077 then([&count](auto h) {
0078 ++count;
0079 REQUIRE(count.load() == 2);
0080 }) |
0081 then([&count](auto h) {
0082 ++count;
0083 REQUIRE(count.load() == 3);
0084 }) |
0085 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0086
0087 h.doneWaiting(std::exception_ptr());
0088 }
0089 waitTask.waitNoThrow();
0090 REQUIRE(count.load() == 3);
0091 REQUIRE(waitTask.done());
0092 REQUIRE(not waitTask.exceptionPtr());
0093 }
0094
0095 SECTION("first | then | then | runLast") {
0096 std::atomic<int> count{0};
0097
0098 oneapi::tbb::task_group group;
0099 edm::FinalWaitingTask waitTask{group};
0100 {
0101 using namespace edm::waiting_task::chain;
0102 first([&count](auto h) {
0103 ++count;
0104 REQUIRE(count.load() == 1);
0105 }) | then([&count](auto h) {
0106 ++count;
0107 REQUIRE(count.load() == 2);
0108 }) | then([&count](auto h) {
0109 ++count;
0110 REQUIRE(count.load() == 3);
0111 }) | runLast(edm::WaitingTaskHolder(group, &waitTask));
0112 }
0113 waitTask.waitNoThrow();
0114 REQUIRE(count.load() == 3);
0115 REQUIRE(waitTask.done());
0116 REQUIRE(not waitTask.exceptionPtr());
0117 }
0118
0119 SECTION("exception -> first | lastTask") {
0120 std::atomic<int> count{0};
0121
0122 oneapi::tbb::task_group group;
0123 edm::FinalWaitingTask waitTask{group};
0124 {
0125 using namespace edm::waiting_task::chain;
0126 auto h = first([&count](edm::WaitingTaskHolder h) {
0127 ++count;
0128 REQUIRE(false);
0129 }) |
0130 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0131
0132 h.doneWaiting(std::make_exception_ptr(std::exception()));
0133 }
0134 waitTask.waitNoThrow();
0135 REQUIRE(count.load() == 0);
0136 REQUIRE(waitTask.done());
0137 REQUIRE(waitTask.exceptionPtr());
0138 }
0139
0140 SECTION("first(exception) | lastTask") {
0141 std::atomic<int> count{0};
0142
0143 oneapi::tbb::task_group group;
0144 edm::FinalWaitingTask waitTask{group};
0145 {
0146 using namespace edm::waiting_task::chain;
0147 auto h = first([&count](edm::WaitingTaskHolder h) {
0148 ++count;
0149 REQUIRE(count.load() == 1);
0150 throw std::exception();
0151 }) |
0152 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0153
0154 h.doneWaiting(std::exception_ptr());
0155 }
0156 waitTask.waitNoThrow();
0157 REQUIRE(count.load() == 1);
0158 REQUIRE(waitTask.done());
0159 REQUIRE(waitTask.exceptionPtr());
0160 }
0161
0162 SECTION("first(exception) | then | then | lastTask") {
0163 std::atomic<int> count{0};
0164
0165 oneapi::tbb::task_group group;
0166 edm::FinalWaitingTask waitTask{group};
0167 {
0168 using namespace edm::waiting_task::chain;
0169 auto h = first([&count](auto h) {
0170 ++count;
0171 REQUIRE(count.load() == 1);
0172 throw std::exception();
0173 }) |
0174 then([&count](auto h) {
0175 ++count;
0176 REQUIRE(false);
0177 }) |
0178 then([&count](auto h) {
0179 ++count;
0180 REQUIRE(false);
0181 }) |
0182 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0183
0184 h.doneWaiting(std::exception_ptr());
0185 }
0186 waitTask.waitNoThrow();
0187 REQUIRE(count.load() == 1);
0188 REQUIRE(waitTask.done());
0189 REQUIRE(waitTask.exceptionPtr());
0190 }
0191 }
0192
0193 SECTION("then with exception handler testing") {
0194 SECTION("first | lastTask") {
0195 std::atomic<int> count{0};
0196
0197 oneapi::tbb::task_group group;
0198 edm::FinalWaitingTask waitTask{group};
0199 {
0200 using namespace edm::waiting_task::chain;
0201 auto h = first([&count](std::exception_ptr const* iPtr, edm::WaitingTaskHolder h) {
0202 REQUIRE(iPtr == nullptr);
0203 ++count;
0204 REQUIRE(count.load() == 1);
0205 }) |
0206 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0207
0208 h.doneWaiting(std::exception_ptr());
0209 }
0210 waitTask.waitNoThrow();
0211 REQUIRE(count.load() == 1);
0212 REQUIRE(waitTask.done());
0213 REQUIRE(not waitTask.exceptionPtr());
0214 }
0215
0216 SECTION("first | then | lastTask") {
0217 std::atomic<int> count{0};
0218
0219 oneapi::tbb::task_group group;
0220 edm::FinalWaitingTask waitTask{group};
0221 {
0222 using namespace edm::waiting_task::chain;
0223 auto h = first([&count](std::exception_ptr const* iPtr, auto h) {
0224 REQUIRE(iPtr == nullptr);
0225 ++count;
0226 REQUIRE(count.load() == 1);
0227 }) |
0228 then([&count](std::exception_ptr const* iPtr, auto h) {
0229 REQUIRE(iPtr == nullptr);
0230 ++count;
0231 REQUIRE(count.load() == 2);
0232 }) |
0233 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0234
0235 h.doneWaiting(std::exception_ptr());
0236 }
0237 waitTask.waitNoThrow();
0238 REQUIRE(count.load() == 2);
0239 REQUIRE(waitTask.done());
0240 REQUIRE(not waitTask.exceptionPtr());
0241 }
0242
0243 SECTION("first | then | then | lastTask") {
0244 std::atomic<int> count{0};
0245
0246 oneapi::tbb::task_group group;
0247 edm::FinalWaitingTask waitTask{group};
0248 {
0249 using namespace edm::waiting_task::chain;
0250 auto h = first([&count](std::exception_ptr const* iPtr, auto h) {
0251 REQUIRE(iPtr == nullptr);
0252 ++count;
0253 REQUIRE(count.load() == 1);
0254 }) |
0255 then([&count](std::exception_ptr const* iPtr, auto h) {
0256 REQUIRE(iPtr == nullptr);
0257 ++count;
0258 REQUIRE(count.load() == 2);
0259 }) |
0260 then([&count](std::exception_ptr const* iPtr, auto h) {
0261 REQUIRE(iPtr == nullptr);
0262 ++count;
0263 REQUIRE(count.load() == 3);
0264 }) |
0265 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0266
0267 h.doneWaiting(std::exception_ptr());
0268 }
0269 waitTask.waitNoThrow();
0270 REQUIRE(count.load() == 3);
0271 REQUIRE(waitTask.done());
0272 REQUIRE(not waitTask.exceptionPtr());
0273 }
0274
0275 SECTION("exception -> first | lastTask") {
0276 std::atomic<int> count{0};
0277
0278 oneapi::tbb::task_group group;
0279 edm::FinalWaitingTask waitTask{group};
0280 {
0281 using namespace edm::waiting_task::chain;
0282 auto h = first([&count](std::exception_ptr const* iPtr, edm::WaitingTaskHolder h) {
0283 REQUIRE(iPtr != nullptr);
0284 ++count;
0285 REQUIRE(count.load() == 1);
0286 }) |
0287 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0288
0289 h.doneWaiting(std::make_exception_ptr(std::exception()));
0290 }
0291 waitTask.waitNoThrow();
0292 REQUIRE(count.load() == 1);
0293 REQUIRE(waitTask.done());
0294 REQUIRE(not waitTask.exceptionPtr());
0295 }
0296
0297 SECTION("exception -> first | then | lastTask") {
0298 std::atomic<int> count{0};
0299
0300 oneapi::tbb::task_group group;
0301 edm::FinalWaitingTask waitTask{group};
0302 {
0303 using namespace edm::waiting_task::chain;
0304 auto h = first([&count](std::exception_ptr const* iPtr, edm::WaitingTaskHolder h) {
0305 REQUIRE(iPtr != nullptr);
0306 ++count;
0307 REQUIRE(count.load() == 1);
0308 h.doneWaiting(*iPtr);
0309 }) |
0310 then([&count](std::exception_ptr const* iPtr, auto h) {
0311 REQUIRE(iPtr != nullptr);
0312 ++count;
0313 REQUIRE(count.load() == 2);
0314 }) |
0315 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0316
0317 h.doneWaiting(std::make_exception_ptr(std::exception()));
0318 }
0319 waitTask.waitNoThrow();
0320 REQUIRE(count.load() == 2);
0321 REQUIRE(waitTask.done());
0322 REQUIRE(not waitTask.exceptionPtr());
0323 }
0324 }
0325
0326 SECTION("ifException.else testing") {
0327 SECTION("first | lastTask") {
0328 std::atomic<int> count{0};
0329 std::atomic<int> exceptCount{0};
0330
0331 oneapi::tbb::task_group group;
0332 edm::FinalWaitingTask waitTask{group};
0333 {
0334 using namespace edm::waiting_task::chain;
0335 auto h = first(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0336 ++exceptCount;
0337 REQUIRE(false);
0338 }).else_([&count](edm::WaitingTaskHolder h) {
0339 ++count;
0340 REQUIRE(count.load() == 1);
0341 })) |
0342 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0343
0344 h.doneWaiting(std::exception_ptr());
0345 }
0346 waitTask.waitNoThrow();
0347 REQUIRE(exceptCount.load() == 0);
0348 REQUIRE(count.load() == 1);
0349 REQUIRE(waitTask.done());
0350 REQUIRE(not waitTask.exceptionPtr());
0351 }
0352
0353 SECTION("first | then | lastTask") {
0354 std::atomic<int> count{0};
0355 std::atomic<int> exceptCount{0};
0356
0357 oneapi::tbb::task_group group;
0358 edm::FinalWaitingTask waitTask{group};
0359 {
0360 using namespace edm::waiting_task::chain;
0361 auto h = first(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0362 ++exceptCount;
0363 REQUIRE(false);
0364 }).else_([&count](auto h) {
0365 ++count;
0366 REQUIRE(count.load() == 1);
0367 })) |
0368 then(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0369 ++exceptCount;
0370 REQUIRE(false);
0371 }).else_([&count](auto h) {
0372 ++count;
0373 REQUIRE(count.load() == 2);
0374 })) |
0375 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0376
0377 h.doneWaiting(std::exception_ptr());
0378 }
0379 waitTask.waitNoThrow();
0380 REQUIRE(exceptCount.load() == 0);
0381 REQUIRE(count.load() == 2);
0382 REQUIRE(waitTask.done());
0383 REQUIRE(not waitTask.exceptionPtr());
0384 }
0385
0386 SECTION("first | then | then | lastTask") {
0387 std::atomic<int> count{0};
0388 std::atomic<int> exceptCount{0};
0389
0390 oneapi::tbb::task_group group;
0391 edm::FinalWaitingTask waitTask{group};
0392 {
0393 using namespace edm::waiting_task::chain;
0394 auto h = first(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0395 ++exceptCount;
0396 REQUIRE(false);
0397 }).else_([&count](auto h) {
0398 ++count;
0399 REQUIRE(count.load() == 1);
0400 })) |
0401 then(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0402 ++exceptCount;
0403 REQUIRE(false);
0404 }).else_([&count](auto h) {
0405 ++count;
0406 REQUIRE(count.load() == 2);
0407 })) |
0408 then(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0409 ++exceptCount;
0410 REQUIRE(false);
0411 }).else_([&count](auto h) {
0412 ++count;
0413 REQUIRE(count.load() == 3);
0414 })) |
0415 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0416
0417 h.doneWaiting(std::exception_ptr());
0418 }
0419 waitTask.waitNoThrow();
0420 REQUIRE(exceptCount.load() == 0);
0421 REQUIRE(count.load() == 3);
0422 REQUIRE(waitTask.done());
0423 REQUIRE(not waitTask.exceptionPtr());
0424 }
0425
0426 SECTION("exception -> first | then | then | lastTask") {
0427 std::atomic<int> count{0};
0428 std::atomic<int> exceptCount{0};
0429
0430 oneapi::tbb::task_group group;
0431 edm::FinalWaitingTask waitTask{group};
0432 {
0433 using namespace edm::waiting_task::chain;
0434 auto h = first(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0435 ++exceptCount;
0436 REQUIRE(exceptCount.load() == 1);
0437 }).else_([&count](auto h) {
0438 ++count;
0439 REQUIRE(false);
0440 })) |
0441 then(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0442 ++exceptCount;
0443 REQUIRE(exceptCount.load() == 2);
0444 }).else_([&count](auto h) {
0445 ++count;
0446 REQUIRE(false);
0447 })) |
0448 then(ifException([&exceptCount](std::exception_ptr const& iPtr) {
0449 ++exceptCount;
0450 REQUIRE(exceptCount.load() == 3);
0451 }).else_([&count](auto h) {
0452 ++count;
0453 REQUIRE(false);
0454 })) |
0455 lastTask(edm::WaitingTaskHolder(group, &waitTask));
0456
0457 h.doneWaiting(std::make_exception_ptr(std::exception()));
0458 }
0459 waitTask.waitNoThrow();
0460 REQUIRE(exceptCount.load() == 3);
0461 REQUIRE(count.load() == 0);
0462 REQUIRE(waitTask.done());
0463 REQUIRE(waitTask.exceptionPtr());
0464 }
0465 }
0466
0467 SECTION("ifThen testing") {
0468 SECTION("first | ifThen(true) | then | runLast") {
0469 std::atomic<int> count{0};
0470
0471 oneapi::tbb::task_group group;
0472 edm::FinalWaitingTask waitTask{group};
0473 {
0474 using namespace edm::waiting_task::chain;
0475 first([&count](auto h) {
0476 ++count;
0477 REQUIRE(count.load() == 1);
0478 }) | ifThen(true, [&count](auto h) {
0479 ++count;
0480 REQUIRE(count.load() == 2);
0481 }) | then([&count](auto h) {
0482 ++count;
0483 REQUIRE(count.load() == 3);
0484 }) | runLast(edm::WaitingTaskHolder(group, &waitTask));
0485 }
0486 waitTask.waitNoThrow();
0487 REQUIRE(count.load() == 3);
0488 REQUIRE(waitTask.done());
0489 REQUIRE(not waitTask.exceptionPtr());
0490 }
0491
0492 SECTION("first | ifThen(false) | then | runLast") {
0493 std::atomic<int> count{0};
0494
0495 oneapi::tbb::task_group group;
0496 edm::FinalWaitingTask waitTask{group};
0497 {
0498 using namespace edm::waiting_task::chain;
0499 first([&count](auto h) {
0500 ++count;
0501 REQUIRE(count.load() == 1);
0502 }) | ifThen(false, [&count](auto h) {
0503 ++count;
0504 REQUIRE(false);
0505 }) | then([&count](auto h) {
0506 ++count;
0507 REQUIRE(count.load() == 2);
0508 }) | runLast(edm::WaitingTaskHolder(group, &waitTask));
0509 }
0510 waitTask.waitNoThrow();
0511 REQUIRE(count.load() == 2);
0512 REQUIRE(waitTask.done());
0513 REQUIRE(not waitTask.exceptionPtr());
0514 }
0515 }
0516 }