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 if (when == std::chrono::nanoseconds::max()) {
189 timer_thread_.ScheduleAt(
190 std::chrono::time_point<std::chrono::high_resolution_clock>::max());
192 timer_thread_.ScheduleAt(std::chrono::high_resolution_clock::now() + when);
196WNDCLASS TaskRunnerWindow::RegisterWindowClass() {
197 window_class_name_ = L
"FlutterTaskRunnerWindow";
199 WNDCLASS window_class{};
200 window_class.hCursor =
nullptr;
201 window_class.lpszClassName = window_class_name_.c_str();
202 window_class.style = 0;
203 window_class.cbClsExtra = 0;
204 window_class.cbWndExtra = 0;
205 window_class.hInstance = GetModuleHandle(
nullptr);
206 window_class.hIcon =
nullptr;
207 window_class.hbrBackground = 0;
208 window_class.lpszMenuName =
nullptr;
209 window_class.lpfnWndProc = WndProc;
210 RegisterClass(&window_class);
217 LPARAM const lparam)
noexcept {
222 wake_up_posted_ =
false;
226 return DefWindowProcW(window_handle_,
message, wparam, lparam);
232 LPARAM const lparam)
noexcept {
233 if (
auto* that =
reinterpret_cast<TaskRunnerWindow*
>(
234 GetWindowLongPtr(
window, GWLP_USERDATA))) {
235 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)