From 3e3e35302ffcae8548dd90325124a254cebac761 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 23 Jun 2022 12:57:06 -0500 Subject: [PATCH] Windows: fixing occasional crashes on Simulator relaunch (#414) --- .../Rtt/Rtt_WinTimer.cpp | 24 +++++++++++++++---- .../Rtt/Rtt_WinTimer.h | 5 ++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.cpp b/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.cpp index e9a587613..3e6792a48 100644 --- a/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.cpp +++ b/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.cpp @@ -15,6 +15,9 @@ namespace Rtt { +std::unordered_map WinTimer::sTimerMap; +UINT_PTR WinTimer::sMostRecentTimerID; + #pragma region Constructors/Destructors WinTimer::WinTimer(MCallback& callback, HWND windowHandle) : PlatformTimer(callback) @@ -46,7 +49,13 @@ void WinTimer::Start() // We do this because Windows timers can invoke later than expected. // To compensate, we'll schedule when to invoke the timer's callback using "fIntervalEndTimeInTicks". fNextIntervalTimeInTicks = (S32)::GetTickCount() + (S32)fIntervalInMilliseconds; - fTimerPointer = ::SetTimer(fWindowHandle, (UINT_PTR)this, 10, WinTimer::OnTimerElapsed); + fTimerID = ++sMostRecentTimerID; // ID should be non-0, so pre-increment for first time + fTimerPointer = ::SetTimer(fWindowHandle, fTimerID, 10, WinTimer::OnTimerElapsed); + + if (IsRunning()) + { + sTimerMap[fTimerID] = this; + } } void WinTimer::Stop() @@ -58,8 +67,12 @@ void WinTimer::Stop() } // Stop the timer. - ::KillTimer(fWindowHandle, fTimerPointer); + ::KillTimer(fWindowHandle, fTimerID); + + sTimerMap.erase(fTimerID); + fTimerPointer = NULL; + fTimerID = 0; } void WinTimer::SetInterval(U32 milliseconds) @@ -99,8 +112,11 @@ void WinTimer::Evaluate() #pragma region Private Methods/Functions VOID CALLBACK WinTimer::OnTimerElapsed(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { - WinTimer *timer = (WinTimer*)idEvent; - timer->Evaluate(); + auto timer = sTimerMap.find(idEvent); + if (sTimerMap.end() != timer) + { + timer->second->Evaluate(); + } } S32 WinTimer::CompareTicks(S32 x, S32 y) diff --git a/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.h b/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.h index 2b70c9409..94b58fb99 100644 --- a/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.h +++ b/platform/windows/Corona.Native.Library.Win32/Rtt/Rtt_WinTimer.h @@ -12,6 +12,7 @@ #include "Core\Rtt_Build.h" #include "Rtt_PlatformTimer.h" #include +#include namespace Rtt @@ -79,8 +80,12 @@ class WinTimer : public PlatformTimer HWND fWindowHandle; UINT_PTR fTimerPointer; + UINT_PTR fTimerID; U32 fIntervalInMilliseconds; S32 fNextIntervalTimeInTicks; + + static std::unordered_map sTimerMap; // timer callback might be called after Stop(), so use this as a guard + static UINT_PTR sMostRecentTimerID; // use an incrementing index as key, to be robust against the rare case that a new timer is reallocated into the same memory }; } // namespace Rtt