terminal/src/cascadia/TerminalControl/ThrottledFunc.cpp
Michael Niksa ea2bd42ff4
Set memory order on slow atomics (#6920)
By default, the memory order on atomics is `seq_cst`. This is a relatively expensive ordering and it shows in situations where we're rapidly signaling a consumer to pick up something from a producer. I've instead attempted to switch these to `release` (producer) and `acquire` (consumer) to improve the performance of these signals. 

## Validation Steps Performed
- Run `time cat big.txt` and `time cat ls.txt` under VS Performance Profiler. 

## PR Checklist
* [x] Closes perf itch
* [x] I work here
* [x] Manual test
* [x] Documentation irrelevant.
* [x] Schema irrelevant.
* [x] Am core contributor.
2020-07-17 17:11:45 +00:00

55 lines
1.5 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "ThrottledFunc.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Xaml;
ThrottledFunc<>::ThrottledFunc(ThrottledFunc::Func func, TimeSpan delay, CoreDispatcher dispatcher) :
_func{ func },
_delay{ delay },
_dispatcher{ dispatcher },
_isRunPending{}
{
}
// Method Description:
// - Runs the function later, except if `Run` is called again before
// with a new argument, in which case the request will be ignored.
// - For more information, read the class' documentation.
// - This method is always thread-safe. It can be called multiple times on
// different threads.
// Arguments:
// - <none>
// Return Value:
// - <none>
void ThrottledFunc<>::Run()
{
if (_isRunPending.test_and_set(std::memory_order_acquire))
{
// already pending
return;
}
_dispatcher.RunAsync(CoreDispatcherPriority::Low, [weakThis = this->weak_from_this()]() {
if (auto self{ weakThis.lock() })
{
DispatcherTimer timer;
timer.Interval(self->_delay);
timer.Tick([=](auto&&...) {
if (auto self{ weakThis.lock() })
{
timer.Stop();
self->_isRunPending.clear(std::memory_order_release);
self->_func();
}
});
timer.Start();
}
});
}