Flutter Engine
event_loop.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/glfw/event_loop.h"
6 
7 #include <atomic>
8 #include <utility>
9 
10 namespace flutter {
11 
13  const TaskExpiredCallback& on_task_expired)
14  : main_thread_id_(main_thread_id),
15  on_task_expired_(std::move(on_task_expired)) {}
16 
17 EventLoop::~EventLoop() = default;
18 
20  return std::this_thread::get_id() == main_thread_id_;
21 }
22 
23 void EventLoop::WaitForEvents(std::chrono::nanoseconds max_wait) {
24  const auto now = TaskTimePoint::clock::now();
25  std::vector<FlutterTask> expired_tasks;
26 
27  // Process expired tasks.
28  {
29  std::lock_guard<std::mutex> lock(task_queue_mutex_);
30  while (!task_queue_.empty()) {
31  const auto& top = task_queue_.top();
32  // If this task (and all tasks after this) has not yet expired, there is
33  // nothing more to do. Quit iterating.
34  if (top.fire_time > now) {
35  break;
36  }
37 
38  // Make a record of the expired task. Do NOT service the task here
39  // because we are still holding onto the task queue mutex. We don't want
40  // other threads to block on posting tasks onto this thread till we are
41  // done processing expired tasks.
42  expired_tasks.push_back(task_queue_.top().task);
43 
44  // Remove the tasks from the delayed tasks queue.
45  task_queue_.pop();
46  }
47  }
48 
49  // Fire expired tasks.
50  {
51  // Flushing tasks here without holing onto the task queue mutex.
52  for (const auto& task : expired_tasks) {
53  on_task_expired_(&task);
54  }
55  }
56 
57  // Sleep till the next task needs to be processed. If a new task comes
58  // along, the wait will be resolved early because PostTask calls Wake().
59  {
60  TaskTimePoint next_wake;
61  {
62  std::lock_guard<std::mutex> lock(task_queue_mutex_);
63  TaskTimePoint max_wake_timepoint =
64  max_wait == std::chrono::nanoseconds::max() ? TaskTimePoint::max()
65  : now + max_wait;
66  TaskTimePoint next_event_timepoint = task_queue_.empty()
67  ? TaskTimePoint::max()
68  : task_queue_.top().fire_time;
69  next_wake = std::min(max_wake_timepoint, next_event_timepoint);
70  }
71  WaitUntil(next_wake);
72  }
73 }
74 
76  uint64_t flutter_target_time_nanos) {
77  const auto now = TaskTimePoint::clock::now();
78  const int64_t flutter_duration =
79  flutter_target_time_nanos - FlutterEngineGetCurrentTime();
80  return now + std::chrono::nanoseconds(flutter_duration);
81 }
82 
83 void EventLoop::PostTask(FlutterTask flutter_task,
84  uint64_t flutter_target_time_nanos) {
85  static std::atomic_uint64_t sGlobalTaskOrder(0);
86 
87  Task task;
88  task.order = ++sGlobalTaskOrder;
89  task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
90  task.task = flutter_task;
91 
92  {
93  std::lock_guard<std::mutex> lock(task_queue_mutex_);
94  task_queue_.push(task);
95 
96  // Make sure the queue mutex is unlocked before waking up the loop. In case
97  // the wake causes this thread to be descheduled for the primary thread to
98  // process tasks, the acquisition of the lock on that thread while holding
99  // the lock here momentarily till the end of the scope is a pessimization.
100  }
101  Wake();
102 }
103 
104 } // namespace flutter
std::priority_queue< Task, std::deque< Task >, Task::Comparer > task_queue_
Definition: event_loop.h:83
std::thread::id main_thread_id_
Definition: event_loop.h:80
std::chrono::steady_clock::time_point TaskTimePoint
Definition: event_loop.h:50
Definition: ref_ptr.h:252
std::function< void(const FlutterTask *)> TaskExpiredCallback
Definition: event_loop.h:22
TaskExpiredCallback on_task_expired_
Definition: event_loop.h:81
EventLoop(std::thread::id main_thread_id, const TaskExpiredCallback &on_task_expired)
Definition: event_loop.cc:12
virtual ~EventLoop()
bool RunsTasksOnCurrentThread() const
Definition: event_loop.cc:19
TaskTimePoint fire_time
Definition: event_loop.h:68
void PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos)
Definition: event_loop.cc:83
std::mutex task_queue_mutex_
Definition: event_loop.h:82
void WaitForEvents(std::chrono::nanoseconds max_wait=std::chrono::nanoseconds::max())
Definition: event_loop.cc:23
static TaskTimePoint TimePointFromFlutterTime(uint64_t flutter_target_time_nanos)
Definition: event_loop.cc:75
int32_t id
virtual void WaitUntil(const TaskTimePoint &time)=0
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
virtual void Wake()=0