Flutter Engine
win32_task_runner.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/shell/platform/windows/win32_task_runner.h"
6 
7 #include <atomic>
8 #include <iostream>
9 #include <utility>
10 
11 namespace flutter {
12 
13 Win32TaskRunner::Win32TaskRunner(DWORD main_thread_id,
14  const TaskExpiredCallback& on_task_expired)
15  : main_thread_id_(main_thread_id),
16  on_task_expired_(std::move(on_task_expired)) {}
17 
19 
21  return GetCurrentThreadId() == main_thread_id_;
22 }
23 
24 std::chrono::nanoseconds Win32TaskRunner::ProcessTasks() {
25  const TaskTimePoint now = TaskTimePoint::clock::now();
26 
27  std::vector<FlutterTask> expired_tasks;
28 
29  // Process expired tasks.
30  {
31  std::lock_guard<std::mutex> lock(task_queue_mutex_);
32  while (!task_queue_.empty()) {
33  const auto& top = task_queue_.top();
34  // If this task (and all tasks after this) has not yet expired, there is
35  // nothing more to do. Quit iterating.
36  if (top.fire_time > now) {
37  break;
38  }
39 
40  // Make a record of the expired task. Do NOT service the task here
41  // because we are still holding onto the task queue mutex. We don't want
42  // other threads to block on posting tasks onto this thread till we are
43  // done processing expired tasks.
44  expired_tasks.push_back(task_queue_.top().task);
45 
46  // Remove the tasks from the delayed tasks queue.
47  task_queue_.pop();
48  }
49  }
50 
51  // Fire expired tasks.
52  {
53  // Flushing tasks here without holing onto the task queue mutex.
54  for (const auto& task : expired_tasks) {
55  on_task_expired_(&task);
56  }
57  }
58 
59  // Calculate duration to sleep for on next iteration.
60  {
61  std::lock_guard<std::mutex> lock(task_queue_mutex_);
62  const auto next_wake = task_queue_.empty() ? TaskTimePoint::max()
63  : task_queue_.top().fire_time;
64 
65  return std::min(next_wake - now, std::chrono::nanoseconds::max());
66  }
67 }
68 
69 Win32TaskRunner::TaskTimePoint Win32TaskRunner::TimePointFromFlutterTime(
70  uint64_t flutter_target_time_nanos) {
71  const auto now = TaskTimePoint::clock::now();
72  const auto flutter_duration =
73  flutter_target_time_nanos - FlutterEngineGetCurrentTime();
74  return now + std::chrono::nanoseconds(flutter_duration);
75 }
76 
78  uint64_t flutter_target_time_nanos) {
79  static std::atomic_uint64_t sGlobalTaskOrder(0);
80 
81  Task task;
82  task.order = ++sGlobalTaskOrder;
83  task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
84  task.task = flutter_task;
85 
86  {
87  std::lock_guard<std::mutex> lock(task_queue_mutex_);
88  task_queue_.push(task);
89 
90  // Make sure the queue mutex is unlocked before waking up the loop. In case
91  // the wake causes this thread to be descheduled for the primary thread to
92  // process tasks, the acquisition of the lock on that thread while holding
93  // the lock here momentarily till the end of the scope is a pessimization.
94  }
95 
96  if (!PostThreadMessage(main_thread_id_, WM_NULL, 0, 0)) {
97  std::cerr << "Failed to post message to main thread." << std::endl;
98  }
99 }
100 
101 } // namespace flutter
std::function< void(const FlutterTask *)> TaskExpiredCallback
void PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos)
Definition: ref_ptr.h:252
Win32TaskRunner(DWORD main_thread_id, const TaskExpiredCallback &on_task_expired)
bool RunsTasksOnCurrentThread() const
std::chrono::nanoseconds ProcessTasks()
uint64_t FlutterEngineGetCurrentTime()
Get the current time in nanoseconds from the clock used by the flutter engine. This is the system mon...
Definition: embedder.cc:1713