diff --git a/src/vault/gear/work-force.hpp b/src/vault/gear/work-force.hpp index 14a2b747f..5d43129ae 100644 --- a/src/vault/gear/work-force.hpp +++ b/src/vault/gear/work-force.hpp @@ -61,15 +61,15 @@ namespace gear { // using std::forward; using std::atomic; using util::unConst; - - using std::chrono_literals::operator ""ms; /////////////WIP namespace work { using std::chrono::milliseconds; + using std::chrono_literals::operator ""ms; - using SIG_WorkFun = activity::Proc(void); + using SIG_WorkFun = activity::Proc(void); ///< config should define callable to perform work + using SIG_FinalHook = void(bool); ///< config should define callable invoked at exit (argument: is error) struct Config { @@ -80,6 +80,7 @@ namespace gear { const size_t DISMISS_CYCLES = 100; }; + /** Individual worker thread: repeatedly pulls the `doWork` functor */ template class Runner : CONF @@ -99,24 +100,34 @@ namespace gear { void pullWork() { - ASSERT_VALID_SIGNATURE (decltype(CONF::doWork), SIG_WorkFun); - - try { - while (true) - { - activity::Proc res = CONF::doWork(); - if (emergency.load (std::memory_order_relaxed)) - break; - if (res == activity::WAIT) - res = idleWait(); - else - idleCycles = 0; - if (res != activity::PASS) - break; - } + ASSERT_VALID_SIGNATURE (decltype(CONF::doWork), SIG_WorkFun); + ASSERT_VALID_SIGNATURE (decltype(CONF::finalHook), SIG_FinalHook); + + bool regularExit{false}; + try /* ================ pull work ===================== */ + { + while (true) + { + activity::Proc res = CONF::doWork(); + if (emergency.load (std::memory_order_relaxed)) + break; + if (res == activity::WAIT) + res = idleWait(); + else + idleCycles = 0; + if (res != activity::PASS) + break; + } + regularExit = true; } ERROR_LOG_AND_IGNORE (threadpool, "defunct worker thread") - ////////////////////////////////////////////////////////////////////////////OOO very important to have a reliable exit-hook here!!! + + try /* ================ thread-exit hook ============== */ + { + CONF::finalHook (not regularExit); + } + ERROR_LOG_AND_IGNORE (threadpool, "failure in thread-exit hook") + thread::detach(); } @@ -199,10 +210,8 @@ namespace gear { { for (auto& w : workers_) w.emergency.store(true, std::memory_order_relaxed); - using namespace std::chrono_literals; ///////////////////////7///WIP - do - std::this_thread::sleep_for(10ms); - while (0 < size()); + while (0 < size()) + std::this_thread::sleep_for(setup_.IDLE_WAIT); } size_t diff --git a/tests/vault/gear/work-force-test.cpp b/tests/vault/gear/work-force-test.cpp index ac426a082..8be546297 100644 --- a/tests/vault/gear/work-force-test.cpp +++ b/tests/vault/gear/work-force-test.cpp @@ -57,6 +57,7 @@ namespace test { namespace { using WorkFun = std::function; + using FinalFun = std::function; template auto @@ -66,6 +67,7 @@ namespace test { : work::Config { WorkFun doWork; + FinalFun finalHook = [](bool){ /*NOP*/ }; milliseconds IDLE_WAIT = work::Config::IDLE_WAIT; size_t DISMISS_CYCLES = work::Config::DISMISS_CYCLES; @@ -74,6 +76,13 @@ namespace test { : doWork{std::forward (workFun)} { } + Setup&& + withFinalHook (FinalFun finalFun) + { + finalHook = move (finalFun); + return move(*this); + } + Setup&& withSleepPeriod (std::chrono::milliseconds millis) { @@ -246,12 +255,27 @@ namespace test { - /** @test TODO - * @todo WIP 9/23 ⟶ define ⟶ implement + /** @test verify invocation of a thread-termination callback */ void verify_finalHook() { + atomic check{0}; + atomic control{activity::PASS}; + WorkForce wof{setup([&]{ return activity::Proc(control); }) + .withFinalHook([&](bool){ ++check; })}; + + CHECK (0 == check); + + wof.activate(); + sleep_for(10ms); + CHECK (wof.size() == work::Config::COMPUTATION_CAPACITY); + CHECK (0 == check); + + control = activity::HALT; + sleep_for(10ms); + CHECK (0 == wof.size()); + CHECK (check == work::Config::COMPUTATION_CAPACITY); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 700671488..e30b6b82f 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -79925,12 +79925,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + @@ -80052,8 +80055,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + +