File indexing completed on 2026-11-09 09:29:08
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Utilities/detail/WorkerPool.hpp"
0012
0013 #include <algorithm>
0014 #include <atomic>
0015 #include <iterator>
0016 #include <stdexcept>
0017 #include <thread>
0018 #include <vector>
0019
0020 using namespace Acts;
0021
0022 namespace ActsTests {
0023
0024 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0025
0026 BOOST_AUTO_TEST_CASE(WorkerPoolVisitsEveryIndexOnce) {
0027 for (std::size_t nThreads : {0u, 1u, 2u, 4u, 7u}) {
0028 detail::WorkerPool pool(nThreads);
0029 BOOST_CHECK_EQUAL(pool.size(), std::max<std::size_t>(nThreads, 1));
0030 for (std::size_t n : {0u, 1u, 2u, 13u, 1000u}) {
0031 for (std::size_t grainSize : {0u, 1u, 3u, 5000u}) {
0032 std::vector<std::atomic<int>> visits(n);
0033 pool.parallelFor(
0034 n, [&](std::size_t i) { visits[i].fetch_add(1); }, grainSize);
0035 for (const auto& v : visits) {
0036 BOOST_CHECK_EQUAL(v.load(), 1);
0037 }
0038 }
0039 }
0040 }
0041 }
0042
0043 BOOST_AUTO_TEST_CASE(WorkerPoolUsesThreads) {
0044 detail::WorkerPool pool(4);
0045 std::vector<std::thread::id> ids(64);
0046 std::atomic<int> waiting{0};
0047 pool.parallelFor(
0048 ids.size(),
0049 [&](std::size_t i) {
0050 ids[i] = std::this_thread::get_id();
0051
0052
0053 if (i < 4) {
0054 waiting.fetch_add(1);
0055 while (waiting.load() < 4) {
0056 std::this_thread::yield();
0057 }
0058 }
0059 },
0060 1);
0061 std::ranges::sort(ids);
0062 auto unique = std::ranges::unique(ids);
0063 BOOST_CHECK_EQUAL(std::distance(ids.begin(), unique.begin()), 4);
0064 }
0065
0066 BOOST_AUTO_TEST_CASE(WorkerPoolRethrows) {
0067 detail::WorkerPool pool(4);
0068 std::atomic<int> calls{0};
0069 BOOST_CHECK_THROW(pool.parallelFor(1000,
0070 [&](std::size_t i) {
0071 calls.fetch_add(1);
0072 if (i == 17) {
0073 throw std::runtime_error("failure");
0074 }
0075 }),
0076 std::runtime_error);
0077 BOOST_CHECK_GE(calls.load(), 1);
0078
0079
0080 std::atomic<std::size_t> sum{0};
0081 pool.parallelFor(100, [&](std::size_t i) { sum.fetch_add(i); });
0082 BOOST_CHECK_EQUAL(sum.load(), 4950u);
0083 }
0084
0085 BOOST_AUTO_TEST_CASE(WorkerPoolNestedAndConcurrentCalls) {
0086 detail::WorkerPool pool(4);
0087
0088
0089 std::atomic<std::size_t> nested{0};
0090 pool.parallelFor(8, [&](std::size_t) {
0091 pool.parallelFor(10, [&](std::size_t) { nested.fetch_add(1); });
0092 });
0093 BOOST_CHECK_EQUAL(nested.load(), 80u);
0094
0095
0096
0097 detail::WorkerPool other(2);
0098 nested.store(0);
0099 pool.parallelFor(8, [&](std::size_t) {
0100 other.parallelFor(2, [&](std::size_t) {
0101 pool.parallelFor(3, [&](std::size_t) { nested.fetch_add(1); });
0102 });
0103 pool.parallelFor(4, [&](std::size_t) { nested.fetch_add(1); });
0104 });
0105 BOOST_CHECK_EQUAL(nested.load(), 80u);
0106
0107
0108 std::atomic<std::size_t> total{0};
0109 std::vector<std::thread> callers;
0110 for (int c = 0; c < 3; ++c) {
0111 callers.emplace_back([&] {
0112 for (int r = 0; r < 20; ++r) {
0113 pool.parallelFor(100, [&](std::size_t) { total.fetch_add(1); });
0114 }
0115 });
0116 }
0117 for (auto& caller : callers) {
0118 caller.join();
0119 }
0120 BOOST_CHECK_EQUAL(total.load(), 3u * 20u * 100u);
0121 }
0122
0123 BOOST_AUTO_TEST_SUITE_END()
0124
0125 }