mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
perf: 优化 Event 的内存占用和性能
This commit is contained in:
parent
f1a82fd8a3
commit
63df4f9a55
17 changed files with 98 additions and 79 deletions
|
|
@ -2,41 +2,45 @@
|
|||
|
||||
namespace Magpie {
|
||||
|
||||
class EventRevoker {
|
||||
template <typename T>
|
||||
class EventRevokerT {
|
||||
public:
|
||||
EventRevoker() noexcept = default;
|
||||
EventRevokerT() noexcept = default;
|
||||
|
||||
EventRevoker(const EventRevoker&) noexcept = delete;
|
||||
EventRevoker(EventRevoker&& other) noexcept = default;
|
||||
EventRevokerT(const EventRevokerT&) noexcept = delete;
|
||||
EventRevokerT(EventRevokerT&& other) noexcept {
|
||||
_Swap(other);
|
||||
}
|
||||
|
||||
EventRevoker& operator=(const EventRevoker& other) noexcept = delete;
|
||||
EventRevoker& operator=(EventRevoker&& other) noexcept {
|
||||
EventRevoker(std::move(other)).Swap(*this);
|
||||
EventRevokerT& operator=(const EventRevokerT&) noexcept = delete;
|
||||
EventRevokerT& operator=(EventRevokerT&& other) noexcept {
|
||||
EventRevokerT(std::move(other))._Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
explicit EventRevoker(T&& revoker) noexcept : _revoker(std::forward<T>(revoker)) {}
|
||||
EventRevokerT(T* event, T::TokenType token) noexcept : _event(event), _token(token) {}
|
||||
|
||||
~EventRevoker() noexcept {
|
||||
if (_revoker) {
|
||||
_revoker();
|
||||
~EventRevokerT() {
|
||||
if (_event) {
|
||||
_event->operator()(_token);
|
||||
}
|
||||
}
|
||||
|
||||
void Swap(EventRevoker& other) noexcept {
|
||||
std::swap(_revoker, other._revoker);
|
||||
}
|
||||
|
||||
void Revoke() {
|
||||
if (_revoker) {
|
||||
_revoker();
|
||||
_revoker = {};
|
||||
if (_event) {
|
||||
_event->operator()(_token);
|
||||
_event = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> _revoker;
|
||||
void _Swap(EventRevokerT& other) noexcept {
|
||||
std::swap(_event, other._event);
|
||||
std::swap(_token, other._token);
|
||||
}
|
||||
|
||||
T* _event = nullptr;
|
||||
T::TokenType _token;
|
||||
};
|
||||
|
||||
struct EventToken {
|
||||
|
|
@ -58,6 +62,9 @@ private:
|
|||
using _FunctionType = std::function<void(TArgs...)>;
|
||||
|
||||
public:
|
||||
using TokenType = EventToken;
|
||||
using EventRevoker = EventRevokerT<Event>;
|
||||
|
||||
#ifdef _DEBUG
|
||||
~Event() {
|
||||
_DEBUG_DELEGATE_COUNT -= (int)_delegates.size();
|
||||
|
|
@ -83,13 +90,10 @@ public:
|
|||
_delegates.erase(it);
|
||||
}
|
||||
|
||||
// 调用者应确保 EventRevoker 在 Event 的生命周期内执行撤销
|
||||
template <typename T>
|
||||
EventRevoker operator()(winrt::auto_revoke_t, T&& handler) {
|
||||
EventToken token = operator()(std::forward<T>(handler));
|
||||
return EventRevoker([this, token]() {
|
||||
// 调用者应确保此函数在 Event 的生命周期内执行
|
||||
operator()(token);
|
||||
});
|
||||
return EventRevoker(this, operator()(std::forward<T>(handler)));
|
||||
}
|
||||
|
||||
template <typename... TArgs1>
|
||||
|
|
@ -112,6 +116,8 @@ private:
|
|||
using _BaseType = Event<TArgs...>;
|
||||
|
||||
public:
|
||||
using EventRevoker = EventRevokerT<MultithreadEvent>;
|
||||
|
||||
template <typename T>
|
||||
EventToken operator()(T&& handler) {
|
||||
auto lock = _lock.lock_exclusive();
|
||||
|
|
@ -126,7 +132,7 @@ public:
|
|||
template <typename T>
|
||||
EventRevoker operator()(winrt::auto_revoke_t, T&& handler) {
|
||||
auto lock = _lock.lock_exclusive();
|
||||
return _BaseType::operator()(winrt::auto_revoke, std::forward<T>(handler));
|
||||
return EventRevoker(this, _BaseType::operator()(std::forward<T>(handler)));
|
||||
}
|
||||
|
||||
template <typename... TArgs1>
|
||||
|
|
@ -142,6 +148,9 @@ private:
|
|||
// 用于简化 WinRT 组件的创建,和 wil::(un)typed_event 相比支持任意委托类型以及 auto revoke
|
||||
template <typename T>
|
||||
struct WinRTEvent {
|
||||
using TokenType = winrt::event_token;
|
||||
using EventRevoker = EventRevokerT<WinRTEvent>;
|
||||
|
||||
winrt::event_token operator()(const T& handler) {
|
||||
return _handler.add(handler);
|
||||
}
|
||||
|
|
@ -152,10 +161,7 @@ struct WinRTEvent {
|
|||
|
||||
EventRevoker operator()(winrt::auto_revoke_t, const T& handler) {
|
||||
winrt::event_token token = operator()(handler);
|
||||
return EventRevoker([this, token]() {
|
||||
// 调用者应确保此函数在 Event 的生命周期内执行
|
||||
operator()(token);
|
||||
});
|
||||
return EventRevoker(this, token);
|
||||
}
|
||||
|
||||
template <typename... TArgs>
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ private:
|
|||
void _UpdateService_StatusChanged(::Magpie::UpdateStatus status);
|
||||
void _UpdateService_DownloadProgressChanged(double);
|
||||
|
||||
::Magpie::EventRevoker _updateStatusChangedRevoker;
|
||||
::Magpie::EventRevoker _downloadProgressChangedRevoker;
|
||||
::Magpie::EventRevoker _showOnHomePageChangedRevoker;
|
||||
::Magpie::Event<::Magpie::UpdateStatus>::EventRevoker _updateStatusChangedRevoker;
|
||||
::Magpie::Event<double>::EventRevoker _downloadProgressChangedRevoker;
|
||||
::Magpie::Event<bool>::EventRevoker _showOnHomePageChangedRevoker;
|
||||
|
||||
Imaging::SoftwareBitmapSource _logo{ nullptr };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ void App::_Uninitialize() {
|
|||
ShortcutService::Get().Uninitialize();
|
||||
ToastService::Get().Uninitialize();
|
||||
|
||||
_colorValuesChangedRevoker.revoke();
|
||||
_isShowNotifyIconChangedRevoker.Revoke();
|
||||
_themeChangedRevoker.Revoke();
|
||||
|
||||
|
|
|
|||
|
|
@ -73,12 +73,12 @@ private:
|
|||
|
||||
CoreDispatcher _dispatcher{ nullptr };
|
||||
|
||||
::Magpie::EventRevoker _themeChangedRevoker;
|
||||
::Magpie::Event<::Magpie::AppTheme>::EventRevoker _themeChangedRevoker;
|
||||
Windows::UI::ViewManagement::UISettings _uiSettings;
|
||||
Windows::UI::ViewManagement::UISettings::ColorValuesChanged_revoker _colorValuesChangedRevoker;
|
||||
std::atomic<bool> _isLightTheme = true;
|
||||
|
||||
::Magpie::EventRevoker _isShowNotifyIconChangedRevoker;
|
||||
::Magpie::Event<bool>::EventRevoker _isShowNotifyIconChangedRevoker;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
|||
|
|
@ -100,11 +100,11 @@ private:
|
|||
|
||||
void _ScalingService_WndToRestoreChanged(HWND);
|
||||
|
||||
::Magpie::EventRevoker _isTimerOnRevoker;
|
||||
::Magpie::EventRevoker _timerTickRevoker;
|
||||
::Magpie::EventRevoker _isRunningChangedRevoker;
|
||||
::Magpie::EventRevoker _wndToRestoreChangedRevoker;
|
||||
::Magpie::EventRevoker _isShowOnHomePageChangedRevoker;
|
||||
::Magpie::Event<bool>::EventRevoker _isTimerOnRevoker;
|
||||
::Magpie::Event<double>::EventRevoker _timerTickRevoker;
|
||||
::Magpie::Event<bool>::EventRevoker _isRunningChangedRevoker;
|
||||
::Magpie::Event<HWND>::EventRevoker _wndToRestoreChangedRevoker;
|
||||
::Magpie::Event<bool>::EventRevoker _isShowOnHomePageChangedRevoker;
|
||||
|
||||
bool _showUpdateCard = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ std::pair<POINT, SIZE> MainWindow::_CreateWindow() noexcept {
|
|||
}
|
||||
|
||||
void MainWindow::_UpdateTheme() noexcept {
|
||||
XamlWindowT::_SetTheme(Content()->ActualTheme() == winrt::ElementTheme::Dark);
|
||||
XamlWindowT::_SetTheme(App::Get().IsLightTheme());
|
||||
}
|
||||
|
||||
LRESULT MainWindow::_TitleBarWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ private:
|
|||
|
||||
void _ResizeTitleBarWindow() noexcept;
|
||||
|
||||
EventRevoker _appThemeChangedRevoker;
|
||||
MultithreadEvent<bool>::EventRevoker _appThemeChangedRevoker;
|
||||
|
||||
HWND _hwndTitleBar = NULL;
|
||||
HWND _hwndMaximizeButton = NULL;
|
||||
|
|
|
|||
|
|
@ -157,8 +157,8 @@ private:
|
|||
// 可以保存此指针的原因是: 用户停留在此页面时不会有缩放配置被创建或删除
|
||||
::Magpie::Profile* _data = nullptr;
|
||||
|
||||
::Magpie::EventRevoker _appThemeChangedRevoker;
|
||||
::Magpie::EventRevoker _dpiChangedRevoker;
|
||||
::Magpie::MultithreadEvent<bool>::EventRevoker _appThemeChangedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _dpiChangedRevoker;
|
||||
|
||||
Controls::IconElement _icon{ nullptr };
|
||||
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ private:
|
|||
|
||||
void _ProfileService_ProfileReordered(uint32_t profileIdx, bool isMoveUp);
|
||||
|
||||
::Magpie::EventRevoker _appThemeChangedRevoker;
|
||||
::Magpie::EventRevoker _dpiChangedRevoker;
|
||||
::Magpie::MultithreadEvent<bool>::EventRevoker _appThemeChangedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _dpiChangedRevoker;
|
||||
|
||||
com_ptr<implementation::NewProfileViewModel> _newProfileViewModel = make_self<implementation::NewProfileViewModel>();
|
||||
::Magpie::EventRevoker _profileAddedRevoker;
|
||||
::Magpie::EventRevoker _profileRenamedRevoker;
|
||||
::Magpie::EventRevoker _profileRemovedRevoker;
|
||||
::Magpie::EventRevoker _profileMovedRevoker;
|
||||
::Magpie::Event<::Magpie::Profile&>::EventRevoker _profileAddedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _profileRenamedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _profileRemovedRevoker;
|
||||
::Magpie::Event<uint32_t, bool>::EventRevoker _profileMovedRevoker;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ private:
|
|||
|
||||
uint32_t _movingFromIdx = 0;
|
||||
|
||||
::Magpie::EventRevoker _scalingModeAddedRevoker;
|
||||
::Magpie::EventRevoker _scalingModeMovedRevoker;
|
||||
::Magpie::EventRevoker _scalingModeRemovedRevoker;
|
||||
::Magpie::Event<::Magpie::EffectAddedWay>::EventRevoker _scalingModeAddedRevoker;
|
||||
::Magpie::Event<uint32_t, bool>::EventRevoker _scalingModeMovedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _scalingModeRemovedRevoker;
|
||||
|
||||
hstring _renameText;
|
||||
std::wstring_view _trimedRenameText;
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ private:
|
|||
|
||||
IObservableVector<IInspectable> _scalingModes = single_threaded_observable_vector<IInspectable>();
|
||||
|
||||
::Magpie::EventRevoker _scalingModeAddedRevoker;
|
||||
::Magpie::EventRevoker _scalingModeMovedRevoker;
|
||||
::Magpie::EventRevoker _scalingModeRemovedRevoker;
|
||||
::Magpie::Event<::Magpie::EffectAddedWay>::EventRevoker _scalingModeAddedRevoker;
|
||||
::Magpie::Event<uint32_t, bool>::EventRevoker _scalingModeMovedRevoker;
|
||||
::Magpie::Event<uint32_t>::EventRevoker _scalingModeRemovedRevoker;
|
||||
|
||||
hstring _newScalingModeName;
|
||||
IVector<IInspectable> _newScalingModeCopyFromList{ nullptr };
|
||||
|
|
|
|||
|
|
@ -75,14 +75,14 @@ private:
|
|||
|
||||
ScalingError _CheckSrcWnd(HWND hWnd, bool checkIL) noexcept;
|
||||
|
||||
std::unique_ptr<::Magpie::ScalingRuntime> _scalingRuntime;
|
||||
std::unique_ptr<ScalingRuntime> _scalingRuntime;
|
||||
|
||||
winrt::DispatcherTimer _countDownTimer;
|
||||
// DispatcherTimer 在不显示主窗口时可能停滞,因此使用 ThreadPoolTimer
|
||||
winrt::Threading::ThreadPoolTimer _checkForegroundTimer{ nullptr };
|
||||
|
||||
EventRevoker _isAutoRestoreChangedRevoker;
|
||||
EventRevoker _shortcutActivatedRevoker;
|
||||
Event<bool>::EventRevoker _isAutoRestoreChangedRevoker;
|
||||
Event<winrt::Magpie::ShortcutAction>::EventRevoker _shortcutActivatedRevoker;
|
||||
|
||||
std::chrono::steady_clock::time_point _timerStartTimePoint;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ private:
|
|||
ShortcutAction _action = ShortcutAction::COUNT_OR_NONE;
|
||||
hstring _title;
|
||||
|
||||
::Magpie::EventRevoker _shortcutChangedRevoker;
|
||||
::Magpie::Event<winrt::Magpie::ShortcutAction>::EventRevoker _shortcutChangedRevoker;
|
||||
|
||||
::Magpie::Shortcut _shortcut;
|
||||
Controls::ContentDialog _shortcutDialog{ nullptr };
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ private:
|
|||
wil::unique_hwnd _hwndHotkey;
|
||||
wil::unique_hhook _keyboardHook;
|
||||
|
||||
::Magpie::EventRevoker _shortcutChangedRevoker;
|
||||
Event<winrt::Magpie::ShortcutAction>::EventRevoker _shortcutChangedRevoker;
|
||||
|
||||
bool _isKeyboardHookActive = true;
|
||||
// 用于防止长按时重复触发热键
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ private:
|
|||
|
||||
void _IsLogoShown(bool value);
|
||||
|
||||
::Magpie::EventRevoker _appThemeChangedRevoker;
|
||||
::Magpie::MultithreadEvent<bool>::EventRevoker _appThemeChangedRevoker;
|
||||
|
||||
Imaging::SoftwareBitmapSource _logo{ nullptr };
|
||||
HWND _hwndToast;
|
||||
|
|
|
|||
|
|
@ -133,7 +133,14 @@ void ToastService::_ToastThreadProc() noexcept {
|
|||
xamlSource.Close();
|
||||
_dispatcher = nullptr;
|
||||
|
||||
// 关闭 DesktopWindowXamlSource 后应清空消息队列
|
||||
// 关闭 DesktopWindowXamlSource 后应清空消息队列以减少 ToastPage 的引用,但不能
|
||||
// 防止泄露
|
||||
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
// 偶尔清空消息队列无用,需要再清空一次,不确定是否 100% 可靠。谢谢你,XAML Islands!
|
||||
Sleep(0);
|
||||
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,16 +83,16 @@ protected:
|
|||
_isMaximized = true;
|
||||
}
|
||||
|
||||
void _SetTheme(bool isDarkTheme) noexcept {
|
||||
_isDarkTheme = isDarkTheme;
|
||||
void _SetTheme(bool isLightTheme) noexcept {
|
||||
_isLightTheme = isLightTheme;
|
||||
|
||||
const HWND hWnd = this->Handle();
|
||||
|
||||
// Win10 中即使在亮色主题下我们也使用暗色边框,这也是 UWP 窗口的行为
|
||||
ThemeHelper::SetWindowTheme(
|
||||
hWnd,
|
||||
Win32Helper::GetOSVersion().IsWin11() ? isDarkTheme : true,
|
||||
isDarkTheme
|
||||
Win32Helper::GetOSVersion().IsWin11() ? !isLightTheme : true,
|
||||
!isLightTheme
|
||||
);
|
||||
|
||||
if (Win32Helper::GetOSVersion().Is22H2OrNewer()) {
|
||||
|
|
@ -108,8 +108,8 @@ protected:
|
|||
HBRUSH hbrOld = (HBRUSH)SetClassLongPtr(
|
||||
hWnd,
|
||||
GCLP_HBRBACKGROUND,
|
||||
(INT_PTR)CreateSolidBrush(isDarkTheme ?
|
||||
ThemeHelper::DARK_TINT_COLOR : ThemeHelper::LIGHT_TINT_COLOR));
|
||||
(INT_PTR)CreateSolidBrush(isLightTheme ? ThemeHelper::LIGHT_TINT_COLOR : ThemeHelper::DARK_TINT_COLOR)
|
||||
);
|
||||
if (hbrOld) {
|
||||
DeleteObject(hbrOld);
|
||||
}
|
||||
|
|
@ -242,18 +242,18 @@ protected:
|
|||
RECT rcRest = ps.rcPaint;
|
||||
rcRest.top = topBorderHeight;
|
||||
|
||||
static bool isDarkBrush = _isDarkTheme;
|
||||
static HBRUSH backgroundBrush = CreateSolidBrush(isDarkBrush ?
|
||||
ThemeHelper::DARK_TINT_COLOR : ThemeHelper::LIGHT_TINT_COLOR);
|
||||
static bool isLightBrush = _isLightTheme;
|
||||
static HBRUSH backgroundBrush = CreateSolidBrush(isLightBrush ?
|
||||
ThemeHelper::LIGHT_TINT_COLOR : ThemeHelper::DARK_TINT_COLOR);
|
||||
|
||||
if (isDarkBrush != _isDarkTheme) {
|
||||
isDarkBrush = _isDarkTheme;
|
||||
if (isLightBrush != _isLightTheme) {
|
||||
isLightBrush = _isLightTheme;
|
||||
DeleteBrush(backgroundBrush);
|
||||
backgroundBrush = CreateSolidBrush(isDarkBrush ?
|
||||
ThemeHelper::DARK_TINT_COLOR : ThemeHelper::LIGHT_TINT_COLOR);
|
||||
backgroundBrush = CreateSolidBrush(isLightBrush ?
|
||||
ThemeHelper::LIGHT_TINT_COLOR : ThemeHelper::DARK_TINT_COLOR);
|
||||
}
|
||||
|
||||
if (isDarkBrush) {
|
||||
if (!isLightBrush) {
|
||||
// 这里我们想要黑色背景而不是原始边框
|
||||
// hack 来自 https://github.com/microsoft/terminal/blob/0ee2c74cd432eda153f3f3e77588164cde95044f/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L1030-L1047
|
||||
HDC opaqueDc;
|
||||
|
|
@ -388,7 +388,7 @@ protected:
|
|||
|
||||
_isMaximized = false;
|
||||
_isWindowShown = false;
|
||||
_isDarkTheme = false;
|
||||
_isLightTheme = true;
|
||||
|
||||
_content = nullptr;
|
||||
|
||||
|
|
@ -401,6 +401,11 @@ protected:
|
|||
while (PeekMessage(&msg1, nullptr, 0, 0, PM_REMOVE)) {
|
||||
DispatchMessage(&msg1);
|
||||
}
|
||||
// 偶尔清空消息队列无用,需要再清空一次,不确定是否 100% 可靠。谢谢你,XAML Islands!
|
||||
Sleep(0);
|
||||
while (PeekMessage(&msg1, nullptr, 0, 0, PM_REMOVE)) {
|
||||
DispatchMessage(&msg1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -512,7 +517,7 @@ private:
|
|||
uint32_t _currentDpi = USER_DEFAULT_SCREEN_DPI;
|
||||
uint32_t _nativeTopBorderHeight = 1;
|
||||
|
||||
bool _isDarkTheme = false;
|
||||
bool _isLightTheme = true;
|
||||
bool _isWindowShown = false;
|
||||
bool _isMaximized = false;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue