• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 OHOS_STANDARD_SYSTEM
19 #include "flutter/fml/platform/linux/message_loop_linux.h"
20 #elif OS_ANDROID
21 #include "flutter/fml/platform/android/message_loop_android.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 
Create()30 fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create() {
31 #if OS_MACOSX
32   return fml::MakeRefCounted<MessageLoopDarwin>();
33 #elif OHOS_STANDARD_SYSTEM
34   return fml::MakeRefCounted<MessageLoopLinux>();
35 #elif OS_ANDROID
36   return fml::MakeRefCounted<MessageLoopAndroid>();
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 
MessageLoopImpl()46 MessageLoopImpl::MessageLoopImpl()
47     : task_queue_(MessageLoopTaskQueues::GetInstance()),
48       queue_id_(task_queue_->CreateTaskQueue()),
49       terminated_(false) {
50   task_queue_->SetWakeable(queue_id_, this);
51 }
52 
~MessageLoopImpl()53 MessageLoopImpl::~MessageLoopImpl() {
54   task_queue_->Dispose(queue_id_);
55 }
56 
PostTask(fml::closure task,fml::TimePoint target_time)57 void MessageLoopImpl::PostTask(fml::closure task, fml::TimePoint target_time) {
58   FML_DCHECK(task != nullptr);
59   FML_DCHECK(task != nullptr);
60   if (terminated_) {
61     // If the message loop has already been terminated, PostTask should destruct
62     // |task| synchronously within this function.
63     return;
64   }
65   task_queue_->RegisterTask(queue_id_, task, target_time);
66 }
67 
AddTaskObserver(intptr_t key,fml::closure callback)68 void MessageLoopImpl::AddTaskObserver(intptr_t key, fml::closure callback) {
69   FML_DCHECK(callback != nullptr);
70   FML_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
71       << "Message loop task observer must be added on the same thread as the "
72          "loop.";
73   if (callback != nullptr) {
74     task_queue_->AddTaskObserver(queue_id_, key, callback);
75   } else {
76     FML_LOG(ERROR) << "Tried to add a null TaskObserver.";
77   }
78 }
79 
RemoveTaskObserver(intptr_t key)80 void MessageLoopImpl::RemoveTaskObserver(intptr_t key) {
81   FML_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this)
82       << "Message loop task observer must be removed from the same thread as "
83          "the loop.";
84   task_queue_->RemoveTaskObserver(queue_id_, key);
85 }
86 
DoRun()87 void MessageLoopImpl::DoRun() {
88   if (terminated_) {
89     // Message loops may be run only once.
90     return;
91   }
92 
93   // Allow the implementation to do its thing.
94   Run();
95 
96   // The loop may have been implicitly terminated. This can happen if the
97   // implementation supports termination via platform specific APIs or just
98   // error conditions. Set the terminated flag manually.
99   terminated_ = true;
100 
101   // The message loop is shutting down. Check if there are expired tasks. This
102   // is the last chance for expired tasks to be serviced. Make sure the
103   // terminated flag is already set so we don't accrue additional tasks now.
104   RunExpiredTasksNow();
105 
106   // When the message loop is in the process of shutting down, pending tasks
107   // should be destructed on the message loop's thread. We have just returned
108   // from the implementations |Run| method which we know is on the correct
109   // thread. Drop all pending tasks on the floor.
110   task_queue_->DisposeTasks(queue_id_);
111 }
112 
DoTerminate()113 void MessageLoopImpl::DoTerminate() {
114   terminated_ = true;
115   Terminate();
116 }
117 
FlushTasks(FlushType type)118 void MessageLoopImpl::FlushTasks(FlushType type) {
119   TRACE_EVENT0("fml", "MessageLoop::FlushTasks");
120   std::vector<fml::closure> invocations;
121 
122   task_queue_->GetTasksToRunNow(queue_id_, type, invocations);
123 
124   for (const auto& invocation : invocations) {
125     invocation();
126     std::vector<fml::closure> observers =
127         task_queue_->GetObserversToNotify(queue_id_);
128     for (const auto& observer : observers) {
129       observer();
130     }
131   }
132 }
133 
RunExpiredTasksNow()134 void MessageLoopImpl::RunExpiredTasksNow() {
135   FlushTasks(FlushType::kAll);
136 }
137 
RunSingleExpiredTaskNow()138 void MessageLoopImpl::RunSingleExpiredTaskNow() {
139   FlushTasks(FlushType::kSingle);
140 }
141 
GetTaskQueueId() const142 TaskQueueId MessageLoopImpl::GetTaskQueueId() const {
143   return queue_id_;
144 }
145 
146 }  // namespace fml
147