diff options
author | Håvard Pettersen <havardpe@yahooinc.com> | 2023-06-20 14:23:30 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@yahooinc.com> | 2023-06-20 14:23:30 +0000 |
commit | cea896a6fad5be3d93b28ecbe752cc0c9468e1c0 (patch) | |
tree | 47b32e7e554e18ec24deb18f942ff4f0014a9c28 /vespalib/src | |
parent | 61860ea094ff79c9e8ca6492c04ad351eeb984f9 (diff) |
Nexus::run is now static
No change for thread lambdas, but they now get separate Nexus objects.
Diffstat (limited to 'vespalib/src')
-rw-r--r-- | vespalib/src/tests/nexus/nexus_test.cpp | 35 | ||||
-rw-r--r-- | vespalib/src/tests/rw_spin_lock/rw_spin_lock_test.cpp | 4 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/test/nexus.cpp | 6 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/test/nexus.h | 38 |
4 files changed, 38 insertions, 45 deletions
diff --git a/vespalib/src/tests/nexus/nexus_test.cpp b/vespalib/src/tests/nexus/nexus_test.cpp index 09f913dccd1..f2fc5b1c218 100644 --- a/vespalib/src/tests/nexus/nexus_test.cpp +++ b/vespalib/src/tests/nexus/nexus_test.cpp @@ -11,10 +11,9 @@ TEST(NexusTest, run_void_tasks) { auto task = [&value](Nexus &) { value.fetch_add(1, std::memory_order_relaxed); }; - Nexus ctx(10); - ctx.run(task); + Nexus::run(10, task); EXPECT_EQ(value, 10); - ctx.run(task); + Nexus::run(10, task); EXPECT_EQ(value, 20); } @@ -24,8 +23,7 @@ TEST(NexusTest, run_value_tasks_select_thread_0) { value.fetch_add(1, std::memory_order_relaxed); return ctx.thread_id() + 5; }; - Nexus ctx(10); - EXPECT_EQ(ctx.run(task), 5); + EXPECT_EQ(Nexus::run(10, task), 5); EXPECT_EQ(value, 10); } @@ -34,8 +32,7 @@ TEST(NexusTest, run_value_tasks_merge_results) { auto task = [&value](Nexus &) { return value.fetch_add(1, std::memory_order_relaxed) + 1; }; - Nexus ctx(10); - EXPECT_EQ(ctx.run(task, Nexus::merge_sum()), 55); + EXPECT_EQ(Nexus::run(10, task, Nexus::merge_sum()), 55); EXPECT_EQ(value, 10); } @@ -46,25 +43,23 @@ TEST(NexusTest, run_inline_voted_loop) { // continue. After 4 iterations, threads 0,1,2,3,4 vote to exit // while threads 5,6,7,8 vote to continue. The result is that all // threads end up doing the loop exactly 4 times. - auto res = Nexus(9).run([](Nexus &ctx) { - size_t times = 0; - for (size_t i = 0; ctx.vote(i < ctx.thread_id()); ++i) { - ++times; - } - return times; - }, [](auto a, auto b){ EXPECT_EQ(a, b); return a; }); + auto res = Nexus::run(9, [](Nexus &ctx) { + size_t times = 0; + for (size_t i = 0; ctx.vote(i < ctx.thread_id()); ++i) { + ++times; + } + return times; + }, [](auto a, auto b){ EXPECT_EQ(a, b); return a; }); EXPECT_EQ(res, 4); } TEST(NexusTest, run_return_type_decay) { int value = 3; auto task = [&](Nexus &)->int&{ return value; }; - Nexus ctx(3); - auto res = ctx.run(task); + auto res = Nexus::run(3, task); EXPECT_EQ(res, 3); - EXPECT_EQ(std::addressof(value), std::addressof(task(ctx))); - using task_res_t = decltype(task(ctx)); - using run_res_t = decltype(ctx.run(task)); + using task_res_t = decltype(task(std::declval<Nexus&>())); + using run_res_t = decltype(Nexus::run(3, task)); static_assert(std::same_as<task_res_t, int&>); static_assert(std::same_as<run_res_t, int>); } @@ -84,7 +79,7 @@ TEST(NexusTest, example_multi_threaded_unit_test) { EXPECT_EQ(a, 5); } }; - Nexus(2).run(work); + Nexus::run(2, work); EXPECT_EQ(a, 5); EXPECT_EQ(b, 7); } diff --git a/vespalib/src/tests/rw_spin_lock/rw_spin_lock_test.cpp b/vespalib/src/tests/rw_spin_lock/rw_spin_lock_test.cpp index 50621338d8c..feb0453d3f8 100644 --- a/vespalib/src/tests/rw_spin_lock/rw_spin_lock_test.cpp +++ b/vespalib/src/tests/rw_spin_lock/rw_spin_lock_test.cpp @@ -187,7 +187,7 @@ BenchmarkResult benchmark_ns(auto &&work, size_t num_threads = 1) { } return result; }; - return Nexus(num_threads).run(entry); + return Nexus::run(num_threads, entry); } //----------------------------------------------------------------------------- @@ -283,7 +283,7 @@ void benchmark_lock() { for (size_t num_threads: {8, 4, 2, 1}) { if (bench || (bp == 9999 && num_threads == 8)) { Meets meets(num_threads); - Nexus(num_threads).run([&](Nexus &ctx) { + Nexus::run(num_threads, [&](Nexus &ctx) { thread_safety_loop(ctx, *lock, *state, meets, bp); }); } diff --git a/vespalib/src/vespa/vespalib/test/nexus.cpp b/vespalib/src/vespa/vespalib/test/nexus.cpp index b5d7b194576..04bd6d26504 100644 --- a/vespalib/src/vespa/vespalib/test/nexus.cpp +++ b/vespalib/src/vespa/vespalib/test/nexus.cpp @@ -4,12 +4,6 @@ namespace vespalib::test { -size_t & -Nexus::my_thread_id() { - thread_local size_t thread_id = invalid_thread_id; - return thread_id; -} - Nexus::~Nexus() = default; } diff --git a/vespalib/src/vespa/vespalib/test/nexus.h b/vespalib/src/vespa/vespalib/test/nexus.h index aeb9337b975..8df840f295d 100644 --- a/vespalib/src/vespa/vespalib/test/nexus.h +++ b/vespalib/src/vespa/vespalib/test/nexus.h @@ -23,27 +23,34 @@ concept nexus_thread_entry = requires(Nexus &ctx, T &&entry) { class Nexus { private: - vespalib::test::ThreadMeets::Vote _vote; - static size_t &my_thread_id(); + using vote_t = vespalib::test::ThreadMeets::Vote; + vote_t &_vote; + size_t _thread_id; + Nexus(vote_t &vote, size_t thread_id) noexcept + : _vote(vote), _thread_id(thread_id) {} + Nexus(Nexus &&) = delete; + Nexus(const Nexus &) = delete; + Nexus &operator=(Nexus &&) = delete; + Nexus &operator=(const Nexus &) = delete; + ~Nexus(); public: - constexpr static size_t invalid_thread_id = -1; - Nexus(size_t num_threads) noexcept : _vote(num_threads) {} size_t num_threads() const noexcept { return _vote.size(); } - size_t thread_id() const noexcept { return my_thread_id(); } + size_t thread_id() const noexcept { return _thread_id; } bool vote(bool my_vote) { return _vote(my_vote); } void barrier() { REQUIRE_EQ(_vote(true), true); } struct select_thread_0 {}; constexpr static auto merge_sum() { return [](auto a, auto b){ return a + b; }; } - auto run(auto &&entry, auto &&merge) requires nexus_thread_entry<decltype(entry)> { + static auto run(size_t num_threads, auto &&entry, auto &&merge) requires nexus_thread_entry<decltype(entry)> { ThreadPool pool; + vote_t vote(num_threads); using result_t = std::decay_t<decltype(entry(std::declval<Nexus&>()))>; constexpr bool is_void = std::same_as<result_t, void>; using stored_t = std::conditional<is_void, std::monostate, result_t>::type; std::mutex lock; std::optional<stored_t> result; - auto handle_result = [&](stored_t thread_result) noexcept { + auto handle_result = [&](Nexus &ctx, stored_t thread_result) noexcept { if constexpr (std::same_as<std::decay_t<decltype(merge)>,select_thread_0>) { - if (thread_id() == 0) { + if (ctx.thread_id() == 0) { result = std::move(thread_result); } } else { @@ -57,16 +64,14 @@ public: } }; auto thread_main = [&](size_t thread_id) noexcept { - size_t old_thread_id = my_thread_id(); - my_thread_id() = thread_id; + Nexus ctx(vote, thread_id); if constexpr (is_void) { - entry(*this); + entry(ctx); } else { - handle_result(entry(*this)); + handle_result(ctx, entry(ctx)); } - my_thread_id() = old_thread_id; }; - for (size_t i = 1; i < num_threads(); ++i) { + for (size_t i = 1; i < num_threads; ++i) { pool.start([i,&thread_main]() noexcept { thread_main(i); }); } thread_main(0); @@ -75,10 +80,9 @@ public: return std::move(result).value(); } } - auto run(auto &&entry) requires nexus_thread_entry<decltype(entry)> { - return run(std::forward<decltype(entry)>(entry), select_thread_0{}); + static auto run(size_t num_threads, auto &&entry) requires nexus_thread_entry<decltype(entry)> { + return run(num_threads, std::forward<decltype(entry)>(entry), select_thread_0{}); } - ~Nexus(); }; } |