Muffle updates to the cursor position to 1/~100ms (#5289)

This stops us from dispatching back-to-back terminal cursor position
updates to the TSF control before it has a chance to get back to us.

Fixes #5288.
This commit is contained in:
Dustin L. Howett (MSFT) 2020-04-08 17:20:51 -07:00 committed by GitHub
parent 6fabc4abb7
commit 1299a839bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 0 deletions

View file

@ -1851,6 +1851,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - N/A
winrt::fire_and_forget TermControl::_TerminalCursorPositionChanged()
{
bool expectedFalse{ false };
if (!_coroutineDispatchStateUpdateInProgress.compare_exchange_weak(expectedFalse, true))
{
// somebody's already in here.
return;
}
if (_closing.load())
{
return;
@ -1858,6 +1865,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
auto weakThis{ get_weak() };
// Muffle 2: Muffle Harder
// If we're the lucky coroutine who gets through, we'll still wait 100ms to clog
// the atomic above so we don't service the cursor update too fast. If we get through
// and finish processing the update quickly but similar requests are still beating
// down the door above in the atomic, we may still update the cursor way more than
// is visible to anyone's eye, which is a waste of effort.
static constexpr auto CursorUpdateQuiesceTime{ std::chrono::milliseconds(100) };
co_await winrt::resume_after(CursorUpdateQuiesceTime);
co_await winrt::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
@ -1866,6 +1882,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
TSFInputControl().TryRedrawCanvas();
}
_coroutineDispatchStateUpdateInProgress.store(false);
}
}

View file

@ -231,6 +231,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void _CompositionCompleted(winrt::hstring text);
void _CurrentCursorPositionHandler(const IInspectable& sender, const CursorPositionEventArgs& eventArgs);
void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs);
// this atomic is to be used as a guard against dispatching billions of coroutines for
// routine state changes that might happen millions of times a second.
// Unbounded main dispatcher use leads to massive memory leaks and intense slowdowns
// on the UI thread.
std::atomic<bool> _coroutineDispatchStateUpdateInProgress{ false };
};
}