-
-
Notifications
You must be signed in to change notification settings - Fork 679
Expand file tree
/
Copy pathGarbageCollectionMonitor.h
More file actions
152 lines (127 loc) · 5.08 KB
/
Copy pathGarbageCollectionMonitor.h
File metadata and controls
152 lines (127 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once
#include "GarbageCollectionMonitor.g.h"
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.System.h>
#include <thread>
#include <mutex>
#include <atomic>
#include <unordered_map>
#include <chrono>
#include <functional>
using PFN_RhGetCurrentObjSize = INT64(__fastcall*)();
using PFN_RhCollect = void(__fastcall*)(int generation, int mode);
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
template<typename Func>
inline void post_to_threadpool(Func&& func)
{
auto* heapFunc = new std::decay_t<Func>(std::forward<Func>(func));
PTP_WORK work = CreateThreadpoolWork(
[](PTP_CALLBACK_INSTANCE, PVOID context, PTP_WORK) {
std::unique_ptr<std::decay_t<Func>> funcPtr(
static_cast<std::decay_t<Func>*>(context)
);
(*funcPtr)();
},
heapFunc,
nullptr
);
SubmitThreadpoolWork(work);
CloseThreadpoolWork(work);
}
namespace winrt::Telegram::Native::implementation
{
struct GarbageCollectionMonitor : GarbageCollectionMonitorT<GarbageCollectionMonitor>
{
using TimeSpan = std::chrono::milliseconds;
static TimeSpan InactivityTimeout;
static TimeSpan DebounceDelay;
static TimeSpan CheckIntervalActive;
static TimeSpan CheckIntervalInactive;
static void Initialize(CollectCallback collectCallback, bool disableGcCollect, bool disablePressure);
static void StartMonitoring(CoreWindow const& window);
static void StopMonitoring(CoreWindow const& window);
static void DisconnectUnusedReferenceSources();
static hstring Debug();
private:
struct WindowState
{
CoreWindow Window{ nullptr };
std::atomic<bool> IsWindowActive{ false };
event_token ActivatedToken{};
event_token ClosedToken{};
WindowState() = default;
explicit WindowState(CoreWindow const& window)
: Window(window), IsWindowActive(false)
{
}
WindowState(WindowState&& other) noexcept
: Window(std::move(other.Window))
, IsWindowActive(other.IsWindowActive.load(std::memory_order_relaxed))
, ActivatedToken(other.ActivatedToken)
, ClosedToken(other.ClosedToken)
{
other.Window = nullptr;
other.ActivatedToken = {};
other.ClosedToken = {};
}
WindowState& operator=(WindowState&& other) noexcept
{
if (this != &other)
{
Window = std::move(other.Window);
IsWindowActive.store(other.IsWindowActive.load(std::memory_order_relaxed), std::memory_order_relaxed);
ActivatedToken = other.ActivatedToken;
ClosedToken = other.ClosedToken;
other.Window = nullptr;
other.ActivatedToken = {};
other.ClosedToken = {};
}
return *this;
}
WindowState(const WindowState&) = delete;
WindowState& operator=(const WindowState&) = delete;
};
static void MonitorThreadProc();
static bool IsAnyWindowActive();
static void TryTriggerCollection();
static void Collect();
static void Detour(bool value);
static std::mutex s_syncLock;
static std::unordered_map<void*, WindowState> s_windowStates;
static std::thread s_monitorThread;
static std::atomic<bool> s_xamlCollectionRequested;
static std::atomic<int64_t> s_lastCollectionTicks;
static std::atomic<int32_t> s_requested;
static std::atomic<int32_t> s_count;
static CollectCallback s_collectCallback;
static DispatcherQueue s_dispatcher;
static Application::Suspending_revoker s_suspending;
static Application::Resuming_revoker s_resuming;
static PFN_RhGetCurrentObjSize s_RhGetCurrentObjSize;
static PFN_RhCollect s_RhCollect;
static std::mutex s_collectLock;
static bool s_collect;
static bool s_suspended;
static INT64 RhGetCurrentObjSize()
{
return 0x7FFFFFFFFFFFFFFF;
}
static void RhCollect(int generation, int mode)
{
post_to_threadpool([&]() { DisconnectUnusedReferenceSources(); });
}
static void OnSuspending(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::ApplicationModel::SuspendingEventArgs const& e);
static void OnResuming(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::Foundation::IInspectable const& e);
};
}
namespace winrt::Telegram::Native::factory_implementation
{
struct GarbageCollectionMonitor : GarbageCollectionMonitorT<GarbageCollectionMonitor, implementation::GarbageCollectionMonitor>
{
};
}