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