From 9d44d1899df54d3a99d24c890a84cd24bbc48cb2 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 15 Nov 2023 23:36:10 +0100 Subject: [PATCH] TaskTree: Fix Timeout activation The activation of one timeout may cancel the other running timeout. Don't remove all timeouts which are to be activated before the activation loop. Remove and activate incrementally instead. Change-Id: I6147fb63b6ef9d6ada034330d98d1c13419012b4 Reviewed-by: hjk Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 49 ++++++++++++------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index bae7c2e17c5..943776c89a4 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -2684,29 +2684,6 @@ struct TimerThreadData // Please note the thread_local keyword below guarantees a separate instance per thread. static thread_local TimerThreadData s_threadTimerData = {}; -static QList prepareForActivation(int timerId) -{ - const auto it = s_threadTimerData.m_timerIdToTimerData.constFind(timerId); - if (it == s_threadTimerData.m_timerIdToTimerData.cend()) - return {}; // the timer was already activated - - const system_clock::time_point deadline = it->m_deadline; - QList toActivate; - auto itMap = s_threadTimerData.m_deadlineToTimerId.cbegin(); - while (itMap != s_threadTimerData.m_deadlineToTimerId.cend()) { - if (itMap.key() > deadline) - break; - - const auto it = s_threadTimerData.m_timerIdToTimerData.constFind(itMap.value()); - if (it != s_threadTimerData.m_timerIdToTimerData.cend()) { - toActivate.append(it.value()); - s_threadTimerData.m_timerIdToTimerData.erase(it); - } - itMap = s_threadTimerData.m_deadlineToTimerId.erase(itMap); - } - return toActivate; -} - static void removeTimerId(int timerId) { const auto it = s_threadTimerData.m_timerIdToTimerData.constFind(timerId); @@ -2722,8 +2699,30 @@ static void removeTimerId(int timerId) static void handleTimeout(int timerId) { - const QList toActivate = prepareForActivation(timerId); - for (const TimerData &timerData : toActivate) { + const auto itData = s_threadTimerData.m_timerIdToTimerData.constFind(timerId); + if (itData == s_threadTimerData.m_timerIdToTimerData.cend()) + return; // The timer was already activated. + + const auto deadline = itData->m_deadline; + while (true) { + const auto itMap = s_threadTimerData.m_deadlineToTimerId.cbegin(); + if (itMap == s_threadTimerData.m_deadlineToTimerId.cend()) + return; + + if (itMap.key() > deadline) + return; + + const auto it = s_threadTimerData.m_timerIdToTimerData.constFind(itMap.value()); + if (it == s_threadTimerData.m_timerIdToTimerData.cend()) { + s_threadTimerData.m_deadlineToTimerId.erase(itMap); + QT_CHECK(false); + return; + } + + const TimerData timerData = it.value(); + s_threadTimerData.m_timerIdToTimerData.erase(it); + s_threadTimerData.m_deadlineToTimerId.erase(itMap); + if (timerData.m_context) timerData.m_callback(); }