1 // Copyright 2018 The Chromium Authors
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 "base/task/current_thread.h"
6
7 #include <utility>
8
9 #include "base/callback_list.h"
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/message_loop/message_pump_for_io.h"
13 #include "base/message_loop/message_pump_for_ui.h"
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/task/sequence_manager/sequence_manager_impl.h"
16 #include "base/threading/thread_local.h"
17 #include "base/trace_event/base_tracing.h"
18 #include "build/build_config.h"
19
20 namespace base {
21
22 //------------------------------------------------------------------------------
23 // CurrentThread
24
25 // static
26 sequence_manager::internal::SequenceManagerImpl*
GetCurrentSequenceManagerImpl()27 CurrentThread::GetCurrentSequenceManagerImpl() {
28 return sequence_manager::internal::SequenceManagerImpl::GetCurrent();
29 }
30
31 // static
Get()32 CurrentThread CurrentThread::Get() {
33 return CurrentThread(GetCurrentSequenceManagerImpl());
34 }
35
36 // static
GetNull()37 CurrentThread CurrentThread::GetNull() {
38 return CurrentThread(nullptr);
39 }
40
41 // static
IsSet()42 bool CurrentThread::IsSet() {
43 return !!GetCurrentSequenceManagerImpl();
44 }
45
AddDestructionObserver(DestructionObserver * destruction_observer)46 void CurrentThread::AddDestructionObserver(
47 DestructionObserver* destruction_observer) {
48 DCHECK(current_->IsBoundToCurrentThread());
49 current_->AddDestructionObserver(destruction_observer);
50 }
51
RemoveDestructionObserver(DestructionObserver * destruction_observer)52 void CurrentThread::RemoveDestructionObserver(
53 DestructionObserver* destruction_observer) {
54 DCHECK(current_->IsBoundToCurrentThread());
55 current_->RemoveDestructionObserver(destruction_observer);
56 }
57
SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner)58 void CurrentThread::SetTaskRunner(
59 scoped_refptr<SingleThreadTaskRunner> task_runner) {
60 DCHECK(current_->IsBoundToCurrentThread());
61 current_->SetTaskRunner(std::move(task_runner));
62 }
63
IsBoundToCurrentThread() const64 bool CurrentThread::IsBoundToCurrentThread() const {
65 return current_ == GetCurrentSequenceManagerImpl();
66 }
67
IsIdleForTesting()68 bool CurrentThread::IsIdleForTesting() {
69 DCHECK(current_->IsBoundToCurrentThread());
70 return current_->IsIdleForTesting();
71 }
72
EnableMessagePumpTimeKeeperMetrics(const char * thread_name)73 void CurrentThread::EnableMessagePumpTimeKeeperMetrics(
74 const char* thread_name) {
75 return current_->EnableMessagePumpTimeKeeperMetrics(thread_name);
76 }
77
AddTaskObserver(TaskObserver * task_observer)78 void CurrentThread::AddTaskObserver(TaskObserver* task_observer) {
79 DCHECK(current_->IsBoundToCurrentThread());
80 current_->AddTaskObserver(task_observer);
81 }
82
RemoveTaskObserver(TaskObserver * task_observer)83 void CurrentThread::RemoveTaskObserver(TaskObserver* task_observer) {
84 DCHECK(current_->IsBoundToCurrentThread());
85 current_->RemoveTaskObserver(task_observer);
86 }
87
SetAddQueueTimeToTasks(bool enable)88 void CurrentThread::SetAddQueueTimeToTasks(bool enable) {
89 DCHECK(current_->IsBoundToCurrentThread());
90 current_->SetAddQueueTimeToTasks(enable);
91 }
92
RegisterOnNextIdleCallback(RegisterOnNextIdleCallbackPasskey,OnceClosure on_next_idle_callback)93 CallbackListSubscription CurrentThread::RegisterOnNextIdleCallback(
94 RegisterOnNextIdleCallbackPasskey,
95 OnceClosure on_next_idle_callback) {
96 return current_->RegisterOnNextIdleCallback(std::move(on_next_idle_callback));
97 }
98
99 CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop::
ScopedAllowApplicationTasksInNativeNestedLoop()100 ScopedAllowApplicationTasksInNativeNestedLoop()
101 : sequence_manager_(GetCurrentSequenceManagerImpl()),
102 previous_state_(
103 sequence_manager_->IsTaskExecutionAllowedInNativeNestedLoop()) {
104 TRACE_EVENT_BEGIN0("base", "ScopedNestableTaskAllower");
105 sequence_manager_->SetTaskExecutionAllowedInNativeNestedLoop(true);
106 }
107
108 CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop::
~ScopedAllowApplicationTasksInNativeNestedLoop()109 ~ScopedAllowApplicationTasksInNativeNestedLoop() {
110 sequence_manager_->SetTaskExecutionAllowedInNativeNestedLoop(previous_state_);
111 TRACE_EVENT_END0("base", "ScopedNestableTaskAllower");
112 }
113
ApplicationTasksAllowedInNativeNestedLoop() const114 bool CurrentThread::ApplicationTasksAllowedInNativeNestedLoop() const {
115 return current_->IsTaskExecutionAllowedInNativeNestedLoop();
116 }
117
118 #if !BUILDFLAG(IS_NACL)
119
120 //------------------------------------------------------------------------------
121 // CurrentUIThread
122
123 // static
Get()124 CurrentUIThread CurrentUIThread::Get() {
125 auto* sequence_manager = GetCurrentSequenceManagerImpl();
126 DCHECK(sequence_manager);
127 #if BUILDFLAG(IS_ANDROID)
128 DCHECK(sequence_manager->IsType(MessagePumpType::UI) ||
129 sequence_manager->IsType(MessagePumpType::JAVA));
130 #else // BUILDFLAG(IS_ANDROID)
131 DCHECK(sequence_manager->IsType(MessagePumpType::UI));
132 #endif // BUILDFLAG(IS_ANDROID)
133 return CurrentUIThread(sequence_manager);
134 }
135
136 // static
IsSet()137 bool CurrentUIThread::IsSet() {
138 sequence_manager::internal::SequenceManagerImpl* sequence_manager =
139 GetCurrentSequenceManagerImpl();
140 return sequence_manager &&
141 #if BUILDFLAG(IS_ANDROID)
142 (sequence_manager->IsType(MessagePumpType::UI) ||
143 sequence_manager->IsType(MessagePumpType::JAVA));
144 #else // BUILDFLAG(IS_ANDROID)
145 sequence_manager->IsType(MessagePumpType::UI);
146 #endif // BUILDFLAG(IS_ANDROID)
147 }
148
GetMessagePumpForUI() const149 MessagePumpForUI* CurrentUIThread::GetMessagePumpForUI() const {
150 return static_cast<MessagePumpForUI*>(current_->GetMessagePump());
151 }
152
153 #if BUILDFLAG(IS_OZONE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForUI::Mode mode,MessagePumpForUI::FdWatchController * controller,MessagePumpForUI::FdWatcher * delegate)154 bool CurrentUIThread::WatchFileDescriptor(
155 int fd,
156 bool persistent,
157 MessagePumpForUI::Mode mode,
158 MessagePumpForUI::FdWatchController* controller,
159 MessagePumpForUI::FdWatcher* delegate) {
160 DCHECK(current_->IsBoundToCurrentThread());
161 return GetMessagePumpForUI()->WatchFileDescriptor(fd, persistent, mode,
162 controller, delegate);
163 }
164 #endif
165
166 #if BUILDFLAG(IS_IOS)
Attach()167 void CurrentUIThread::Attach() {
168 current_->AttachToMessagePump();
169 }
170 #endif // BUILDFLAG(IS_IOS)
171
172 #if BUILDFLAG(IS_ANDROID)
Abort()173 void CurrentUIThread::Abort() {
174 GetMessagePumpForUI()->Abort();
175 }
176 #endif // BUILDFLAG(IS_ANDROID)
177
178 #if BUILDFLAG(IS_WIN)
AddMessagePumpObserver(MessagePumpForUI::Observer * observer)179 void CurrentUIThread::AddMessagePumpObserver(
180 MessagePumpForUI::Observer* observer) {
181 GetMessagePumpForUI()->AddObserver(observer);
182 }
183
RemoveMessagePumpObserver(MessagePumpForUI::Observer * observer)184 void CurrentUIThread::RemoveMessagePumpObserver(
185 MessagePumpForUI::Observer* observer) {
186 GetMessagePumpForUI()->RemoveObserver(observer);
187 }
188 #endif // BUILDFLAG(IS_WIN)
189
190 #endif // !BUILDFLAG(IS_NACL)
191
192 //------------------------------------------------------------------------------
193 // CurrentIOThread
194
195 // static
Get()196 CurrentIOThread CurrentIOThread::Get() {
197 auto* sequence_manager = GetCurrentSequenceManagerImpl();
198 DCHECK(sequence_manager);
199 DCHECK(sequence_manager->IsType(MessagePumpType::IO));
200 return CurrentIOThread(sequence_manager);
201 }
202
203 // static
IsSet()204 bool CurrentIOThread::IsSet() {
205 auto* sequence_manager = GetCurrentSequenceManagerImpl();
206 return sequence_manager && sequence_manager->IsType(MessagePumpType::IO);
207 }
208
GetMessagePumpForIO() const209 MessagePumpForIO* CurrentIOThread::GetMessagePumpForIO() const {
210 return static_cast<MessagePumpForIO*>(current_->GetMessagePump());
211 }
212
213 #if !BUILDFLAG(IS_NACL)
214
215 #if BUILDFLAG(IS_WIN)
RegisterIOHandler(HANDLE file,MessagePumpForIO::IOHandler * handler)216 HRESULT CurrentIOThread::RegisterIOHandler(
217 HANDLE file,
218 MessagePumpForIO::IOHandler* handler) {
219 DCHECK(current_->IsBoundToCurrentThread());
220 return GetMessagePumpForIO()->RegisterIOHandler(file, handler);
221 }
222
RegisterJobObject(HANDLE job,MessagePumpForIO::IOHandler * handler)223 bool CurrentIOThread::RegisterJobObject(HANDLE job,
224 MessagePumpForIO::IOHandler* handler) {
225 DCHECK(current_->IsBoundToCurrentThread());
226 return GetMessagePumpForIO()->RegisterJobObject(job, handler);
227 }
228
229 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForIO::Mode mode,MessagePumpForIO::FdWatchController * controller,MessagePumpForIO::FdWatcher * delegate)230 bool CurrentIOThread::WatchFileDescriptor(
231 int fd,
232 bool persistent,
233 MessagePumpForIO::Mode mode,
234 MessagePumpForIO::FdWatchController* controller,
235 MessagePumpForIO::FdWatcher* delegate) {
236 DCHECK(current_->IsBoundToCurrentThread());
237 return GetMessagePumpForIO()->WatchFileDescriptor(fd, persistent, mode,
238 controller, delegate);
239 }
240 #endif // BUILDFLAG(IS_WIN)
241
242 #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
WatchMachReceivePort(mach_port_t port,MessagePumpForIO::MachPortWatchController * controller,MessagePumpForIO::MachPortWatcher * delegate)243 bool CurrentIOThread::WatchMachReceivePort(
244 mach_port_t port,
245 MessagePumpForIO::MachPortWatchController* controller,
246 MessagePumpForIO::MachPortWatcher* delegate) {
247 DCHECK(current_->IsBoundToCurrentThread());
248 return GetMessagePumpForIO()->WatchMachReceivePort(port, controller,
249 delegate);
250 }
251 #endif
252
253 #endif // !BUILDFLAG(IS_NACL)
254
255 #if BUILDFLAG(IS_FUCHSIA)
256 // Additional watch API for native platform resources.
WatchZxHandle(zx_handle_t handle,bool persistent,zx_signals_t signals,MessagePumpForIO::ZxHandleWatchController * controller,MessagePumpForIO::ZxHandleWatcher * delegate)257 bool CurrentIOThread::WatchZxHandle(
258 zx_handle_t handle,
259 bool persistent,
260 zx_signals_t signals,
261 MessagePumpForIO::ZxHandleWatchController* controller,
262 MessagePumpForIO::ZxHandleWatcher* delegate) {
263 DCHECK(current_->IsBoundToCurrentThread());
264 return GetMessagePumpForIO()->WatchZxHandle(handle, persistent, signals,
265 controller, delegate);
266 }
267 #endif
268
269 } // namespace base
270