Flutter Windows Embedder
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 
6 
7 #include <atomic>
8 #include <utility>
9 
10 namespace flutter {
11 
13  const TaskExpiredCallback& on_task_expired)
14  : get_current_time_(get_current_time),
15  on_task_expired_(std::move(on_task_expired)) {
16  main_thread_id_ = GetCurrentThreadId();
17  task_runner_window_ = TaskRunnerWindow::GetSharedInstance();
18  task_runner_window_->AddDelegate(this);
19 }
20 
22  task_runner_window_->RemoveDelegate(this);
23 }
24 
25 std::chrono::nanoseconds TaskRunner::ProcessTasks() {
26  const TaskTimePoint now = GetCurrentTimeForTask();
27 
28  std::vector<Task> expired_tasks;
29 
30  // Process expired tasks.
31  {
32  std::lock_guard<std::mutex> lock(task_queue_mutex_);
33  while (!task_queue_.empty()) {
34  const auto& top = task_queue_.top();
35  // If this task (and all tasks after this) has not yet expired, there is
36  // nothing more to do. Quit iterating.
37  if (top.fire_time > now) {
38  break;
39  }
40 
41  // Make a record of the expired task. Do NOT service the task here
42  // because we are still holding onto the task queue mutex. We don't want
43  // other threads to block on posting tasks onto this thread till we are
44  // done processing expired tasks.
45  expired_tasks.push_back(task_queue_.top());
46 
47  // Remove the tasks from the delayed tasks queue.
48  task_queue_.pop();
49  }
50  }
51 
52  // Fire expired tasks.
53  {
54  // Flushing tasks here without holing onto the task queue mutex.
55  for (const auto& task : expired_tasks) {
56  if (auto flutter_task = std::get_if<FlutterTask>(&task.variant)) {
57  on_task_expired_(flutter_task);
58  } else if (auto closure = std::get_if<TaskClosure>(&task.variant))
59  (*closure)();
60  }
61  }
62 
63  // Calculate duration to sleep for on next iteration.
64  {
65  std::lock_guard<std::mutex> lock(task_queue_mutex_);
66  if (task_queue_.empty()) {
67  return std::chrono::nanoseconds::max();
68  } else {
69  return task_queue_.top().fire_time - now;
70  }
71  }
72 }
73 
74 TaskRunner::TaskTimePoint TaskRunner::TimePointFromFlutterTime(
75  uint64_t flutter_target_time_nanos) const {
76  const auto now = GetCurrentTimeForTask();
77  const auto flutter_duration = flutter_target_time_nanos - get_current_time_();
78  return now + std::chrono::nanoseconds(flutter_duration);
79 }
80 
81 void TaskRunner::PostFlutterTask(FlutterTask flutter_task,
82  uint64_t flutter_target_time_nanos) {
83  Task task;
84  task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
85  task.variant = flutter_task;
86  EnqueueTask(std::move(task));
87 }
88 
90  Task task;
91  task.fire_time = GetCurrentTimeForTask();
92  task.variant = std::move(closure);
93  EnqueueTask(std::move(task));
94 }
95 
96 void TaskRunner::PollOnce(std::chrono::milliseconds timeout) {
97  task_runner_window_->PollOnce(timeout);
98 }
99 
100 void TaskRunner::EnqueueTask(Task task) {
101  static std::atomic_uint64_t sGlobalTaskOrder(0);
102 
103  task.order = ++sGlobalTaskOrder;
104  {
105  std::lock_guard<std::mutex> lock(task_queue_mutex_);
106  task_queue_.push(task);
107 
108  // Make sure the queue mutex is unlocked before waking up the loop. In case
109  // the wake causes this thread to be descheduled for the primary thread to
110  // process tasks, the acquisition of the lock on that thread while holding
111  // the lock here momentarily till the end of the scope is a pessimization.
112  }
113 
114  WakeUp();
115 }
116 
118  return GetCurrentThreadId() == main_thread_id_;
119 }
120 
121 void TaskRunner::WakeUp() {
122  task_runner_window_->WakeUp();
123 }
124 
125 } // namespace flutter
std::chrono::steady_clock::time_point TaskTimePoint
Definition: task_runner.h:28
void PostFlutterTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos)
Definition: task_runner.cc:81
TaskRunner(CurrentTimeProc get_current_time, const TaskExpiredCallback &on_task_expired)
Definition: task_runner.cc:12
virtual ~TaskRunner()
Definition: task_runner.cc:21
virtual bool RunsTasksOnCurrentThread() const
Definition: task_runner.cc:117
std::function< void(const FlutterTask *)> TaskExpiredCallback
Definition: task_runner.h:29
void PollOnce(std::chrono::milliseconds timeout)
Definition: task_runner.cc:96
std::function< void()> TaskClosure
Definition: task_runner.h:30
void PostTask(TaskClosure task)
Definition: task_runner.cc:89
std::chrono::nanoseconds ProcessTasks()
Definition: task_runner.cc:25
static std::shared_ptr< TaskRunnerWindow > GetSharedInstance()
uint64_t(* CurrentTimeProc)()
Definition: task_runner.h:21