From 129f6403d832d3293a02d39e3e3ac0e0a68d5e63 Mon Sep 17 00:00:00 2001 From: InvictusMB Date: Sun, 21 Jun 2020 18:16:36 +0200 Subject: [PATCH] Fix high CPU load #708 --- .../CursesDriver/UnixMainLoop.cs | 35 ++++++++----------- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 30 ++++++++-------- Terminal.Gui/Core/MainLoop.cs | 4 ++- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs index 83ccf9837..d6fc9d987 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs @@ -168,45 +168,38 @@ namespace Terminal.Gui { bool IMainLoopDriver.EventsPending (bool wait) { - int pollTimeout = 0; - int n; - - if (CkeckTimeout (wait, ref pollTimeout)) + if (CheckTimers (wait, out var pollTimeout)) { return true; + } UpdatePollMap (); - while (true) { - n = poll (pollmap, (uint)pollmap.Length, 0); - if (pollmap != null) { - break; - } - if (mainLoop.idleHandlers.Count > 0 || CkeckTimeout (wait, ref pollTimeout)) { - return true; - } - } - int ic; - lock (mainLoop.idleHandlers) - ic = mainLoop.idleHandlers.Count; - return n > 0 || mainLoop.timeouts.Count > 0 && ((mainLoop.timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0; + var n = poll (pollmap, (uint)pollmap.Length, pollTimeout); + + return n > 0 || CheckTimers (wait, out pollTimeout); } - bool CkeckTimeout (bool wait, ref int pollTimeout) + bool CheckTimers (bool wait, out int pollTimeout) { long now = DateTime.UtcNow.Ticks; if (mainLoop.timeouts.Count > 0) { pollTimeout = (int)((mainLoop.timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond); - if (pollTimeout < 0) + if (pollTimeout < 0) { return true; - + } } else pollTimeout = -1; if (!wait) pollTimeout = 0; - return false; + int ic; + lock (mainLoop.idleHandlers) { + ic = mainLoop.idleHandlers.Count; + } + + return ic > 0; } void IMainLoopDriver.MainIteration () diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 9c85fec76..c507f9122 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -615,24 +615,16 @@ namespace Terminal.Gui { bool IMainLoopDriver.EventsPending (bool wait) { - int waitTimeout = 0; - - if (CkeckTimeout (wait, ref waitTimeout)) + if (CheckTimers (wait, out var waitTimeout)) { return true; + } result = null; waitForProbe.Set (); try { - while (result == null) { - if (!tokenSource.IsCancellationRequested) - eventReady.Wait (0, tokenSource.Token); - if (result != null) { - break; - } - if (mainLoop.idleHandlers.Count > 0 || CkeckTimeout (wait, ref waitTimeout)) { - return true; - } + if (!tokenSource.IsCancellationRequested) { + eventReady.Wait (waitTimeout, tokenSource.Token); } } catch (OperationCanceledException) { return true; @@ -640,15 +632,16 @@ namespace Terminal.Gui { eventReady.Reset (); } - if (!tokenSource.IsCancellationRequested) - return result != null; + if (!tokenSource.IsCancellationRequested) { + return result != null || CheckTimers (wait, out waitTimeout); + } tokenSource.Dispose (); tokenSource = new CancellationTokenSource (); return true; } - bool CkeckTimeout (bool wait, ref int waitTimeout) + bool CheckTimers (bool wait, out int waitTimeout) { long now = DateTime.UtcNow.Ticks; @@ -663,7 +656,12 @@ namespace Terminal.Gui { if (!wait) waitTimeout = 0; - return false; + int ic; + lock (mainLoop.idleHandlers) { + ic = mainLoop.idleHandlers.Count; + } + + return ic > 0; } Action keyHandler; diff --git a/Terminal.Gui/Core/MainLoop.cs b/Terminal.Gui/Core/MainLoop.cs index 8e1217ad6..22bfa372a 100644 --- a/Terminal.Gui/Core/MainLoop.cs +++ b/Terminal.Gui/Core/MainLoop.cs @@ -95,9 +95,11 @@ namespace Terminal.Gui { /// Token that can be used to remove the idle handler with . public Func AddIdle (Func idleHandler) { - lock (idleHandlers) + lock (idleHandlers) { idleHandlers.Add (idleHandler); + } + Driver.Wakeup (); return idleHandler; }