diff --git a/src/thread/AsyncBack.cpp b/src/thread/AsyncBack.cpp index 5bdada5..70e99cd 100644 --- a/src/thread/AsyncBack.cpp +++ b/src/thread/AsyncBack.cpp @@ -20,9 +20,10 @@ bool AsyncBack::newTaskOK(const MT_TaskEntryFN& mt_aEntryFN, const TaskBackFN& a fut_backFN_S_.emplace_back( // save future<> & aBackFN() async( launch::async, - [mt_aEntryFN]() // must cp than ref, otherwise dead loop + [mt_aEntryFN, this]() // must cp than ref, otherwise dead loop { const bool 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 a53fc30..dba265c 100644 --- a/src/thread/ThPoolBack.cpp +++ b/src/thread/ThPoolBack.cpp @@ -41,6 +41,7 @@ ThPoolBack::ThPoolBack(size_t aMaxThread) this->taskQ_.pop_front(); } task(); + this->nDoneTh_.fetch_add(1, std::memory_order_relaxed); // fastest +1 mt_pingMainTH(); // notify mainTH 1 task done } }); diff --git a/src/thread/ThPoolBack.hpp b/src/thread/ThPoolBack.hpp index 506c3bf..867588d 100644 --- a/src/thread/ThPoolBack.hpp +++ b/src/thread/ThPoolBack.hpp @@ -11,7 +11,8 @@ // // MT safe: NO (can be used in main thread only) // Exception-safe: NO -// Use-safe: yes +// Use-safe: yes with condition: +// - shall not too many tasks that exceeds fut_backFN_S_/nDoneTh_/.. (impossible in most/normal cases) // *********************************************************************************************** #pragma once diff --git a/src/thread/ThreadBack.cpp b/src/thread/ThreadBack.cpp index 843df66..1808fb4 100644 --- a/src/thread/ThreadBack.cpp +++ b/src/thread/ThreadBack.cpp @@ -17,24 +17,25 @@ namespace rlib // *********************************************************************************************** size_t ThreadBack::hdlFinishedTasks(UniLog& oneLog) { - size_t nHandled = 0; - for (auto&& fut_backFN = fut_backFN_S_.begin(); fut_backFN != fut_backFN_S_.end();) // may limit# if too many + size_t nHandledTh = 0; + const auto nDoneTh = nDoneTh_.exchange(0, memory_order_relaxed); + for (auto&& fut_backFN = fut_backFN_S_.begin(); nHandledTh < nDoneTh && fut_backFN != fut_backFN_S_.end();) { // - async() failure will throw exception -> terminate since compiling forbid exception // - valid async()'s future never invalid // - valid packaged_task's get_future() never invalid auto&& fut = fut_backFN->first; - // HID("(ThreadBack) nHandled=" << nHandled << ", valid=" << fut.valid() << ", backFn=" << &(fut_backFN->second)); + // HID("(ThreadBack) nHandledTh=" << nHandledTh << ", valid=" << fut.valid() << ", backFn=" << &(fut_backFN->second)); if (fut.wait_for(0s) == future_status::ready) { fut_backFN->second(fut.get()); // callback fut_backFN = fut_backFN_S_.erase(fut_backFN); - ++nHandled; + ++nHandledTh; } else ++fut_backFN; } // 1 loop, simple & safe - return nHandled; + return nHandledTh; } // *********************************************************************************************** diff --git a/src/thread/ThreadBack.hpp b/src/thread/ThreadBack.hpp index c09736b..d55ef93 100644 --- a/src/thread/ThreadBack.hpp +++ b/src/thread/ThreadBack.hpp @@ -10,6 +10,7 @@ // *********************************************************************************************** #pragma once +#include #include #include #include @@ -54,7 +55,8 @@ class ThreadBack protected: // ------------------------------------------------------------------------------------------- - StoreThreadBack fut_backFN_S_; + StoreThreadBack fut_backFN_S_; // must save future till thread end + std::atomic nDoneTh_ = 0; // improve main thread to search done thread(s) }; } // namespace @@ -62,4 +64,5 @@ class ThreadBack // YYYY-MM-DD Who v)Modification Description // .......... ......... ....................................................................... // 2024-07-09 CSZ 1)create +// 2024-08-05 CSZ - nDoneTh_ to improve iteration of fut_backFN_S_ // ***********************************************************************************************