From ded1cae1c13d73a129e1aea374a76158828cbc09 Mon Sep 17 00:00:00 2001 From: fchn289 Date: Mon, 5 Aug 2024 18:37:59 +0800 Subject: [PATCH] ThreadBack: EntryFN ret SafePtr than bool --- src/thread/AsyncBack.cpp | 2 +- src/thread/ThPoolBack.cpp | 4 +- src/thread/ThPoolBack.hpp | 2 +- src/thread/ThreadBack.hpp | 14 +++++-- src/thread/ThreadBackViaMsgSelf.hpp | 2 +- ut/thread/ThPoolBackTest.cpp | 12 +++--- ut/thread/ThreadBackTest.hpp | 61 +++++++++++++---------------- 7 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/thread/AsyncBack.cpp b/src/thread/AsyncBack.cpp index 70e99cd..a20375c 100644 --- a/src/thread/AsyncBack.cpp +++ b/src/thread/AsyncBack.cpp @@ -22,7 +22,7 @@ bool AsyncBack::newTaskOK(const MT_TaskEntryFN& mt_aEntryFN, const TaskBackFN& a launch::async, [mt_aEntryFN, this]() // must cp than ref, otherwise dead loop { - const bool ret = mt_aEntryFN(); + auto ret = mt_aEntryFN(); this->nDoneTh_.fetch_add(1, std::memory_order_relaxed); // fastest +1 mt_pingMainTH(); return ret; diff --git a/src/thread/ThPoolBack.cpp b/src/thread/ThPoolBack.cpp index dba265c..6de4b3d 100644 --- a/src/thread/ThPoolBack.cpp +++ b/src/thread/ThPoolBack.cpp @@ -28,7 +28,7 @@ ThPoolBack::ThPoolBack(size_t aMaxThread) { // thread main() for (;;) { - packaged_task task; + packaged_task()> task; { unique_lock lock(this->mutex_); this->cv_.wait(lock, [this]{ return this->stopAllTH_ || !this->taskQ_.empty(); }); @@ -68,7 +68,7 @@ bool ThPoolBack::newTaskOK(const MT_TaskEntryFN& mt_aEntryFN, const TaskBackFN& if (! ThreadBack::newTaskOK(mt_aEntryFN, aBackFN, oneLog)) return false; - packaged_task task(mt_aEntryFN); // packaged_task can get_future()="task result" + packaged_task()> task(mt_aEntryFN); // packaged_task can get_future()="task result" fut_backFN_S_.emplace_back(task.get_future(), aBackFN); // save future<> & aBackFN() { unique_lock lock(mutex_); diff --git a/src/thread/ThPoolBack.hpp b/src/thread/ThPoolBack.hpp index 356aae2..d976dc3 100644 --- a/src/thread/ThPoolBack.hpp +++ b/src/thread/ThPoolBack.hpp @@ -40,7 +40,7 @@ class ThPoolBack : public ThreadBack private: // ------------------------------------------------------------------------------------------- std::vector thPool_; - std::deque> taskQ_; + std::deque()>> taskQ_; std::mutex mutex_; std::condition_variable cv_; diff --git a/src/thread/ThreadBack.hpp b/src/thread/ThreadBack.hpp index d55ef93..c89ea4c 100644 --- a/src/thread/ThreadBack.hpp +++ b/src/thread/ThreadBack.hpp @@ -4,9 +4,13 @@ * SPDX-License-Identifier: BSD-3-Clause */ // *********************************************************************************************** -// - Why: +// - Why this class: // . support both async() & thread pool // . common here, special in AsyncBack or ThPoolBack +// +// - why SafePtr +// . thread can ret any type data include bool +// . safe convert from SafePtr to correct data // *********************************************************************************************** #pragma once @@ -17,6 +21,7 @@ #include #include "MT_PingMainTH.hpp" +#include "SafePtr.hpp" #include "UniLog.hpp" #define THREAD_BACK (rlib::ObjAnywhere::getObj()) @@ -24,9 +29,9 @@ namespace rlib { // *********************************************************************************************** -using MT_TaskEntryFN = std::function; // succ ret true, otherwise false -using TaskBackFN = std::function; // entry ret as para -using StoreThreadBack = std::list, TaskBackFN> >; // deque rm middle is worse +using MT_TaskEntryFN = std::function()>; // ret-nullptr means failure +using TaskBackFN = std::function)>; // MT_TaskEntryFN's ret as para +using StoreThreadBack = std::list>, TaskBackFN> >; // deque is worse when rm mid // *********************************************************************************************** class ThreadBack @@ -65,4 +70,5 @@ class ThreadBack // .......... ......... ....................................................................... // 2024-07-09 CSZ 1)create // 2024-08-05 CSZ - nDoneTh_ to improve iteration of fut_backFN_S_ +// - MT_TaskEntryFN ret SafePtr instead of bool // *********************************************************************************************** diff --git a/src/thread/ThreadBackViaMsgSelf.hpp b/src/thread/ThreadBackViaMsgSelf.hpp index 1b76a95..abf9bfb 100644 --- a/src/thread/ThreadBackViaMsgSelf.hpp +++ b/src/thread/ThreadBackViaMsgSelf.hpp @@ -26,7 +26,7 @@ TaskBackFN viaMsgSelf(const TaskBackFN& aBackFN, std::shared_ptr aMsgSe { return ! aBackFN || aMsgSelf == nullptr ? TaskBackFN(nullptr) // empty fn - : [aBackFN, aMsgSelf, aPri](bool aRet) // must cp aBackFN since lambda run later in diff lifecycle + : [aBackFN, aMsgSelf, aPri](SafePtr aRet) // must cp aBackFN since lambda run later in diff lifecycle { aMsgSelf->newMsg(bind(aBackFN, aRet), aPri); // wrap aBackFN to queue in MsgSelf }; diff --git a/ut/thread/ThPoolBackTest.cpp b/ut/thread/ThPoolBackTest.cpp index d7d7197..a50f413 100644 --- a/ut/thread/ThPoolBackTest.cpp +++ b/ut/thread/ThPoolBackTest.cpp @@ -11,8 +11,8 @@ TEST_F(ThPoolBackTest, invalid_maxThread) { ThPoolBack myPool(0); // invalid maxThread=0 EXPECT_TRUE(threadBack_.newTaskOK( - [] { return true; }, // entryFn - [](bool) {} // backFn + [] { return make_safe(true); }, // entryFn + [](SafePtr) {} // backFn )) << "REQ: can create new task"; while (threadBack_.hdlFinishedTasks() == 0) timedwait(); // REQ: wait new task done @@ -30,9 +30,9 @@ TEST_F(ThPoolBackTest, performance) [] // entryFn { this_thread::yield(); // hung like real time-cost task - return true; + return make_safe(true); }, - [](bool) {} // backFn + [](SafePtr) {} // backFn )); for (size_t nHandled = 0; nHandled < maxThread; nHandled += thPoolBack.hdlFinishedTasks()) timedwait(); @@ -48,9 +48,9 @@ TEST_F(ThPoolBackTest, performance) [] // entryFn { this_thread::yield(); // hung like real time-cost task - return true; + return make_safe(true); }, - [](bool) {} // backFn + [](SafePtr) {} // backFn )); for (size_t nHandled = 0; nHandled < maxThread; nHandled += asyncBack.hdlFinishedTasks()) timedwait(); diff --git a/ut/thread/ThreadBackTest.hpp b/ut/thread/ThreadBackTest.hpp index 4aecf36..d0f0a03 100644 --- a/ut/thread/ThreadBackTest.hpp +++ b/ut/thread/ThreadBackTest.hpp @@ -58,27 +58,22 @@ TEST_F(THREAD_BACK_TEST, GOLD_entryFn_inNewThread_thenBackFn_inMainThread_withTi EXPECT_TRUE(ThreadBack::inMyMainTH()) << "REQ: OK in main thread"; EXPECT_TRUE(threadBack_.newTaskOK( // MT_TaskEntryFN - [this]() -> bool + [this]() { EXPECT_FALSE(ThreadBack::inMyMainTH()) << "REQ: in new thread"; - return true; + return make_safe(true); }, // TaskBackFN - [this](bool) + [this](SafePtr) { EXPECT_TRUE(ThreadBack::inMyMainTH()) << "REQ: in main thread"; } )); - while (true) + while (threadBack_.hdlFinishedTasks() == 0) { - if (threadBack_.hdlFinishedTasks() == 0) - { - INF("new thread not end yet..."); - timedwait(); // REQ: timedwait() is more efficient than keep hdlFinishedTasks() - continue; - } - return; + INF("new thread not end yet..."); + timedwait(); // REQ: timedwait() is more efficient than keep hdlFinishedTasks() } } TEST_F(THREAD_BACK_TEST, GOLD_entryFnResult_toBackFn_withoutTimedWait) @@ -89,14 +84,14 @@ TEST_F(THREAD_BACK_TEST, GOLD_entryFnResult_toBackFn_withoutTimedWait) SCOPED_TRACE(idxThread); EXPECT_TRUE(threadBack_.newTaskOK( // MT_TaskEntryFN - [idxThread]() -> bool + [idxThread]() { - return idxThread % 2 != 0; // ret true / false + return make_safe(idxThread % 2 != 0); // ret true / false }, // TaskBackFN - [idxThread](bool aRet) + [idxThread](SafePtr aRet) { - EXPECT_EQ(idxThread % 2 != 0, aRet) << "REQ: check true & false"; + EXPECT_EQ(idxThread % 2 != 0, *(dynamic_pointer_cast(aRet).get())) << "REQ: check true & false"; } )); } @@ -112,24 +107,24 @@ TEST_F(THREAD_BACK_TEST, canHandle_someThreadDone_whileOtherRunning) atomic canEnd(false); threadBack_.newTaskOK( // MT_TaskEntryFN - [&canEnd]() -> bool + [&canEnd]() { while (not canEnd) this_thread::yield(); // not end until instruction - return true; + return make_safe(true); }, // TaskBackFN - [](bool) {} + [](SafePtr) {} ); threadBack_.newTaskOK( // MT_TaskEntryFN - []() -> bool + []() { - return false; // quick end + return make_safe(false); // quick end }, // TaskBackFN - [](bool) {} + [](SafePtr) {} ); while (threadBack_.hdlFinishedTasks() == 0) @@ -152,8 +147,8 @@ TEST_F(THREAD_BACK_TEST, GOLD_entryFn_notify_insteadof_timeout) { auto start = high_resolution_clock::now(); threadBack_.newTaskOK( - [] { return true; }, // entryFn - [](bool) {} // backFn + [] { return make_safe(true); }, // entryFn + [](SafePtr) {} // backFn ); timedwait(0, 500'000'000); // long timer to ensure thread done beforehand auto dur = duration_cast(high_resolution_clock::now() - start); @@ -173,16 +168,16 @@ TEST_F(THREAD_BACK_TEST, emptyThreadList_ok) TEST_F(THREAD_BACK_TEST, invalid_msgSelf_entryFN_backFN) { EXPECT_FALSE(threadBack_.newTaskOK( - [] { return true; }, // entryFn - viaMsgSelf([](bool) {}, nullptr) // invalid since msgSelf==nullptr + [] { return make_safe(true); }, // entryFn + viaMsgSelf([](SafePtr) {}, nullptr) // invalid since msgSelf==nullptr )); EXPECT_FALSE(threadBack_.newTaskOK( - [] { return true; }, // entryFn + [] { return make_safe(true); }, // entryFn viaMsgSelf(nullptr, msgSelf_) // invalid since backFn==nullptr )); EXPECT_FALSE(threadBack_.newTaskOK( MT_TaskEntryFN(nullptr), // invalid since entryFn==nullptr - [](bool) {} // backFn + [](SafePtr) {} // backFn )); EXPECT_EQ(0, threadBack_.nThread()); } @@ -223,13 +218,13 @@ TEST_F(THREAD_BACK_TEST, GOLD_integrate_MsgSelf_ThreadBack_MtInQueue) // simula // entryFn [] { mt_getQ().mt_push(MAKE_PTR("a")); - return true; + return make_safe(true); }, // backFn viaMsgSelf( // REQ: via MsgSelf - [this, &cb_info](bool aRet) + [this, &cb_info](SafePtr aRet) { - EXPECT_TRUE(aRet) << "entryFn succ"; + EXPECT_TRUE(*(dynamic_pointer_cast(aRet).get())) << "entryFn succ"; cb_info.emplace("REQ: a's backFn via MsgSelf"); }, msgSelf_ @@ -239,13 +234,13 @@ TEST_F(THREAD_BACK_TEST, GOLD_integrate_MsgSelf_ThreadBack_MtInQueue) // simula // entryFn [] { mt_getQ().mt_push(MAKE_PTR(2)); - return true; + return make_safe(true); }, // backFn viaMsgSelf( - [this, &cb_info](bool aRet) + [this, &cb_info](SafePtr aRet) { - EXPECT_TRUE(aRet) << "entryFn succ"; + EXPECT_TRUE(*(dynamic_pointer_cast(aRet).get())) << "entryFn succ"; cb_info.emplace("REQ: 2's backFn via MsgSelf"); }, msgSelf_