Flutter Engine
message_loop_impl.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 #define FML_USED_ON_EMBEDDER
6 
7 #include "flutter/fml/message_loop_impl.h"
8 
9 #include <algorithm>
10 #include <vector>
11 
12 #include "flutter/fml/build_config.h"
13 #include "flutter/fml/logging.h"
14 #include "flutter/fml/trace_event.h"
15 
16 #if OS_MACOSX
17 #include "flutter/fml/platform/darwin/message_loop_darwin.h"
18 #elif OS_ANDROID
19 #include "flutter/fml/platform/android/message_loop_android.h"
20 #elif OS_FUCHSIA
21 #include "flutter/fml/platform/fuchsia/message_loop_fuchsia.h"
22 #elif OS_LINUX
23 #include "flutter/fml/platform/linux/message_loop_linux.h"
24 #elif OS_WIN
25 #include "flutter/fml/platform/win/message_loop_win.h"
26 #endif
27 
28 namespace fml {
29 
31 #if OS_MACOSX
32  return fml::MakeRefCounted<MessageLoopDarwin>();
33 #elif OS_ANDROID
34  return fml::MakeRefCounted<MessageLoopAndroid>();
35 #elif OS_FUCHSIA
36  return fml::MakeRefCounted<MessageLoopFuchsia>();
37 #elif OS_LINUX
38  return fml::MakeRefCounted<MessageLoopLinux>();
39 #elif OS_WIN
40  return fml::MakeRefCounted<MessageLoopWin>();
41 #else
42  return nullptr;
43 #endif
44 }
45 
47  : task_queue_(MessageLoopTaskQueues::GetInstance()),
48  queue_id_(task_queue_->CreateTaskQueue()),
49  terminated_(false) {
50  task_queue_->SetWakeable(queue_id_, this);
51 }
52 
54  task_queue_->Dispose(queue_id_);
55 }
56 
58  fml::TimePoint target_time) {
59  FML_DCHECK(task != nullptr);
60  FML_DCHECK(task != nullptr);
61  if (terminated_) {
62  // If the message loop has already been terminated, PostTask should destruct
63  // |task| synchronously within this function.
64  return;
65  }
66  task_queue_->RegisterTask(queue_id_, task, target_time);
67 }
68 
70  const fml::closure& callback) {
71  FML_DCHECK(callback != nullptr);
72  FML_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
73  << "Message loop task observer must be added on the same thread as the "
74  "loop.";
75  if (callback != nullptr) {
76  task_queue_->AddTaskObserver(queue_id_, key, callback);
77  } else {
78  FML_LOG(ERROR) << "Tried to add a null TaskObserver.";
79  }
80 }
81 
83  FML_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
84  << "Message loop task observer must be removed from the same thread as "
85  "the loop.";
86  task_queue_->RemoveTaskObserver(queue_id_, key);
87 }
88 
90  if (terminated_) {
91  // Message loops may be run only once.
92  return;
93  }
94 
95  // Allow the implementation to do its thing.
96  Run();
97 
98  // The loop may have been implicitly terminated. This can happen if the
99  // implementation supports termination via platform specific APIs or just
100  // error conditions. Set the terminated flag manually.
101  terminated_ = true;
102 
103  // The message loop is shutting down. Check if there are expired tasks. This
104  // is the last chance for expired tasks to be serviced. Make sure the
105  // terminated flag is already set so we don't accrue additional tasks now.
107 
108  // When the message loop is in the process of shutting down, pending tasks
109  // should be destructed on the message loop's thread. We have just returned
110  // from the implementations |Run| method which we know is on the correct
111  // thread. Drop all pending tasks on the floor.
112  task_queue_->DisposeTasks(queue_id_);
113 }
114 
116  terminated_ = true;
117  Terminate();
118 }
119 
120 void MessageLoopImpl::FlushTasks(FlushType type) {
121  TRACE_EVENT0("fml", "MessageLoop::FlushTasks");
122 
123  const auto now = fml::TimePoint::Now();
124  fml::closure invocation;
125  do {
126  invocation = task_queue_->GetNextTaskToRun(queue_id_, now);
127  if (!invocation) {
128  break;
129  }
130  invocation();
131  std::vector<fml::closure> observers =
132  task_queue_->GetObserversToNotify(queue_id_);
133  for (const auto& observer : observers) {
134  observer();
135  }
136  if (type == FlushType::kSingle) {
137  break;
138  }
139  } while (invocation);
140 }
141 
143  FlushTasks(FlushType::kAll);
144 }
145 
147  FlushTasks(FlushType::kSingle);
148 }
149 
151  return queue_id_;
152 }
153 
154 } // namespace fml
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
#define FML_DCHECK(condition)
Definition: logging.h:86
void RemoveTaskObserver(intptr_t key)
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
#define FML_LOG(severity)
Definition: logging.h:65
Definition: ascii_trie.cc:9
std::function< void()> closure
Definition: closure.h:14
virtual void Run()=0
static fml::RefPtr< MessageLoopImpl > Create()
void PostTask(const fml::closure &task, fml::TimePoint target_time)
void AddTaskObserver(intptr_t key, const fml::closure &callback)
virtual TaskQueueId GetTaskQueueId() const
virtual void Terminate()=0
static TimePoint Now()
Definition: time_point.cc:26