Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-24 02:18:39

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