@@ -17,17 +17,20 @@ size_t ThreadBack::hdlDoneFut(UniLog& oneLog) noexcept
1717 if (nDoneFut == 0 ) return 0 ;
1818 // HID("(ThreadBack) nHandled=" << nHandledFut << '/' << nDoneFut << '|' << nFut());
1919
20- // bugFix: may mt_nDoneFut_+1 before future::ready, so must check "fut_backFN != fut_backFN_S_.end()"
21- for (auto && fut_backFN = fut_backFN_S_. begin (); nHandledFut < nDoneFut && fut_backFN != fut_backFN_S_. end () ;)
20+ // bugFix: may mt_nDoneFut_+1 before future::ready, so must check size
21+ for (size_t i = 0 ; i < fut_backFN_S_. size () && nHandledFut < nDoneFut ;)
2222 {
2323 // - async() failure will throw exception -> terminate since compiling forbid exception
2424 // - valid async()'s future never invalid
2525 // - valid packaged_task's get_future() never invalid
26- auto & fut = fut_backFN-> first ;
26+ auto & fut = fut_backFN_S_[i]. first ;
2727 if (fut.wait_for (0s) == future_status::ready)
2828 {
29- auto task_pair = std::move (*fut_backFN);
30- fut_backFN = fut_backFN_S_.erase (fut_backFN);
29+ auto task_pair = std::move (fut_backFN_S_[i]);
30+ // swap-erase: move last element into this slot, then pop_back
31+ if (i + 1 < fut_backFN_S_.size ())
32+ fut_backFN_S_[i] = std::move (fut_backFN_S_.back ());
33+ fut_backFN_S_.pop_back ();
3134 ++nHandledFut;
3235
3336 SafePtr ret;
@@ -38,7 +41,7 @@ size_t ThreadBack::hdlDoneFut(UniLog& oneLog) noexcept
3841 catch (...) { ERR (" (ThreadBack) backFN() except" ); } // ERR() ok since in main thread
3942 }
4043 else
41- ++fut_backFN ;
44+ ++i ;
4245 } // 1 loop, simple & safe
4346
4447 mt_nDoneFut_.fetch_sub (nHandledFut, memory_order_relaxed); // memory_order_relaxed is faster but not so realtime
0 commit comments