Skip to content

Commit

Permalink
Muffle updates to the cursor position to 1/~100ms (#5289)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
DHowett authored Apr 9, 2020
1 parent 6fabc4a commit 1299a83
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1851,13 +1851,29 @@ 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;
}

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() })
Expand All @@ -1866,6 +1882,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
TSFInputControl().TryRedrawCanvas();
}
_coroutineDispatchStateUpdateInProgress.store(false);
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
};
}

Expand Down

0 comments on commit 1299a83

Please sign in to comment.