21 std::chrono::time_point<
std::chrono::high_resolution_clock>::max()) {}
26 std::make_optional<std::thread>(&TimerThread::TimerThreadMain,
this);
34 std::lock_guard<std::mutex> lock(mutex_);
50 std::chrono::time_point<std::chrono::high_resolution_clock> time_point) {
51 std::lock_guard<std::mutex> lock(mutex_);
52 if (time_point < next_fire_time_) {
53 next_fire_time_ = time_point;
59void TimerThread::TimerThreadMain() {
60 std::unique_lock<std::mutex> lock(mutex_);
61 while (callback_ !=
nullptr) {
62 cv_.wait_until(lock, next_fire_time_, [
this]() {
63 return std::chrono::high_resolution_clock::now() >= next_fire_time_ ||
66 auto scheduled_count = schedule_counter_;
73 if (scheduled_count == schedule_counter_ &&
74 next_fire_time_ <= std::chrono::high_resolution_clock::now()) {
76 std::chrono::time_point<std::chrono::high_resolution_clock>::max();
84TaskRunnerWindow::TaskRunnerWindow() : timer_thread_([this]() { OnTimer(); }) {
85 WNDCLASS window_class = RegisterWindowClass();
87 CreateWindowEx(0, window_class.lpszClassName, L
"", 0, 0, 0, 0, 0,
88 HWND_MESSAGE,
nullptr, window_class.hInstance,
nullptr);
91 SetWindowLongPtr(window_handle_, GWLP_USERDATA,
93 timer_thread_.Start();
97 size_t size = FormatMessageW(
98 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
99 FORMAT_MESSAGE_IGNORE_INSERTS,
100 NULL,
error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
101 reinterpret_cast<LPWSTR
>(&
message), 0, NULL);
106 thread_id_ = GetCurrentThreadId();
109TaskRunnerWindow::~TaskRunnerWindow() {
110 timer_thread_.Stop();
112 if (window_handle_) {
113 DestroyWindow(window_handle_);
114 window_handle_ =
nullptr;
116 UnregisterClass(window_class_name_.c_str(),
nullptr);
119void TaskRunnerWindow::OnTimer() {
123void TaskRunnerWindow::TimerProc(PTP_CALLBACK_INSTANCE
instance,
126 reinterpret_cast<TaskRunnerWindow*
>(context)->OnTimer();
129std::shared_ptr<TaskRunnerWindow> TaskRunnerWindow::GetSharedInstance() {
130 static std::weak_ptr<TaskRunnerWindow>
instance;
140void TaskRunnerWindow::WakeUp() {
141 bool expected =
false;
145 if (wake_up_posted_.compare_exchange_strong(expected,
true)) {
147 FML_LOG(ERROR) <<
"Failed to post message to main thread.";
152void TaskRunnerWindow::AddDelegate(
Delegate* delegate) {
153 delegates_.push_back(delegate);
154 SetTimer(std::chrono::nanoseconds::zero());
157void TaskRunnerWindow::RemoveDelegate(
Delegate* delegate) {
158 auto i = std::find(delegates_.begin(), delegates_.end(), delegate);
159 if (
i != delegates_.end()) {
164void TaskRunnerWindow::PollOnce(std::chrono::milliseconds timeout) {
168 TranslateMessage(&msg);
174void TaskRunnerWindow::ProcessTasks() {
175 auto next = std::chrono::nanoseconds::max();
176 auto delegates_copy(delegates_);
177 for (
auto delegate : delegates_copy) {
179 if (std::find(delegates_.begin(), delegates_.end(), delegate) !=
181 next = std::min(next, delegate->ProcessTasks());
187void TaskRunnerWindow::SetTimer(std::chrono::nanoseconds when) {
188 auto now = std::chrono::high_resolution_clock::now();
189 auto remaining_to_max =
190 std::chrono::nanoseconds::max() - now.time_since_epoch();
191 when = std::min(when, remaining_to_max);
192 timer_thread_.ScheduleAt(now + when);
195WNDCLASS TaskRunnerWindow::RegisterWindowClass() {
196 window_class_name_ = L
"FlutterTaskRunnerWindow";
198 WNDCLASS window_class{};
199 window_class.hCursor =
nullptr;
200 window_class.lpszClassName = window_class_name_.c_str();
201 window_class.style = 0;
202 window_class.cbClsExtra = 0;
203 window_class.cbWndExtra = 0;
204 window_class.hInstance = GetModuleHandle(
nullptr);
205 window_class.hIcon =
nullptr;
206 window_class.hbrBackground = 0;
207 window_class.lpszMenuName =
nullptr;
208 window_class.lpfnWndProc = WndProc;
209 RegisterClass(&window_class);
216 LPARAM const lparam)
noexcept {
221 wake_up_posted_ =
false;
225 return DefWindowProcW(window_handle_,
message, wparam, lparam);
231 LPARAM const lparam)
noexcept {
232 if (
auto* that =
reinterpret_cast<TaskRunnerWindow*
>(
233 GetWindowLongPtr(
window, GWLP_USERDATA))) {
234 return that->HandleMessage(
message, wparam, lparam);
void ScheduleAt(std::chrono::time_point< std::chrono::high_resolution_clock > time_point)
TimerThread(std::function< void()> callback)
const uint8_t uint32_t uint32_t GError ** error
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
#define FML_DCHECK(condition)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static const uintptr_t kPollTimeoutTimerId
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)