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,bool wall_time_based_metrics_enabled_for_testing)73 void CurrentThread::EnableMessagePumpTimeKeeperMetrics(
74 const char* thread_name,
75 bool wall_time_based_metrics_enabled_for_testing) {
76 return current_->EnableMessagePumpTimeKeeperMetrics(
77 thread_name, wall_time_based_metrics_enabled_for_testing);
78 }
79
GetIOWatcher()80 IOWatcher* CurrentThread::GetIOWatcher() {
81 DCHECK(current_->IsBoundToCurrentThread());
82 return current_->GetMessagePump()->GetIOWatcher();
83 }
84
AddTaskObserver(TaskObserver * task_observer)85 void CurrentThread::AddTaskObserver(TaskObserver* task_observer) {
86 DCHECK(current_->IsBoundToCurrentThread());
87 current_->AddTaskObserver(task_observer);
88 }
89
RemoveTaskObserver(TaskObserver * task_observer)90 void CurrentThread::RemoveTaskObserver(TaskObserver* task_observer) {
91 DCHECK(current_->IsBoundToCurrentThread());
92 current_->RemoveTaskObserver(task_observer);
93 }
94
SetAddQueueTimeToTasks(bool enable)95 void CurrentThread::SetAddQueueTimeToTasks(bool enable) {
96 DCHECK(current_->IsBoundToCurrentThread());
97 current_->SetAddQueueTimeToTasks(enable);
98 }
99
RegisterOnNextIdleCallback(RegisterOnNextIdleCallbackPasskey,OnceClosure on_next_idle_callback)100 CallbackListSubscription CurrentThread::RegisterOnNextIdleCallback(
101 RegisterOnNextIdleCallbackPasskey,
102 OnceClosure on_next_idle_callback) {
103 return current_->RegisterOnNextIdleCallback(std::move(on_next_idle_callback));
104 }
105
106 CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop::
ScopedAllowApplicationTasksInNativeNestedLoop()107 ScopedAllowApplicationTasksInNativeNestedLoop()
108 : sequence_manager_(GetCurrentSequenceManagerImpl()),
109 previous_state_(
110 sequence_manager_->IsTaskExecutionAllowedInNativeNestedLoop()) {
111 TRACE_EVENT_BEGIN0("base", "ScopedNestableTaskAllower");
112 sequence_manager_->SetTaskExecutionAllowedInNativeNestedLoop(true);
113 }
114
115 CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop::
~ScopedAllowApplicationTasksInNativeNestedLoop()116 ~ScopedAllowApplicationTasksInNativeNestedLoop() {
117 sequence_manager_->SetTaskExecutionAllowedInNativeNestedLoop(previous_state_);
118 TRACE_EVENT_END0("base", "ScopedNestableTaskAllower");
119 }
120
ApplicationTasksAllowedInNativeNestedLoop() const121 bool CurrentThread::ApplicationTasksAllowedInNativeNestedLoop() const {
122 return current_->IsTaskExecutionAllowedInNativeNestedLoop();
123 }
124
125 #if !BUILDFLAG(IS_NACL)
126
127 //------------------------------------------------------------------------------
128 // CurrentUIThread
129
130 // static
Get()131 CurrentUIThread CurrentUIThread::Get() {
132 auto* sequence_manager = GetCurrentSequenceManagerImpl();
133 DCHECK(sequence_manager);
134 #if BUILDFLAG(IS_ANDROID)
135 DCHECK(sequence_manager->IsType(MessagePumpType::UI) ||
136 sequence_manager->IsType(MessagePumpType::JAVA));
137 #else // BUILDFLAG(IS_ANDROID)
138 DCHECK(sequence_manager->IsType(MessagePumpType::UI));
139 #endif // BUILDFLAG(IS_ANDROID)
140 return CurrentUIThread(sequence_manager);
141 }
142
143 // static
IsSet()144 bool CurrentUIThread::IsSet() {
145 sequence_manager::internal::SequenceManagerImpl* sequence_manager =
146 GetCurrentSequenceManagerImpl();
147 return sequence_manager &&
148 #if BUILDFLAG(IS_ANDROID)
149 (sequence_manager->IsType(MessagePumpType::UI) ||
150 sequence_manager->IsType(MessagePumpType::JAVA));
151 #else // BUILDFLAG(IS_ANDROID)
152 sequence_manager->IsType(MessagePumpType::UI);
153 #endif // BUILDFLAG(IS_ANDROID)
154 }
155
GetMessagePumpForUI() const156 MessagePumpForUI* CurrentUIThread::GetMessagePumpForUI() const {
157 return static_cast<MessagePumpForUI*>(current_->GetMessagePump());
158 }
159
160 #if BUILDFLAG(IS_OZONE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForUI::Mode mode,MessagePumpForUI::FdWatchController * controller,MessagePumpForUI::FdWatcher * delegate)161 bool CurrentUIThread::WatchFileDescriptor(
162 int fd,
163 bool persistent,
164 MessagePumpForUI::Mode mode,
165 MessagePumpForUI::FdWatchController* controller,
166 MessagePumpForUI::FdWatcher* delegate) {
167 DCHECK(current_->IsBoundToCurrentThread());
168 return GetMessagePumpForUI()->WatchFileDescriptor(fd, persistent, mode,
169 controller, delegate);
170 }
171 #endif
172
173 #if BUILDFLAG(IS_IOS)
Attach()174 void CurrentUIThread::Attach() {
175 current_->AttachToMessagePump();
176 }
177 #endif // BUILDFLAG(IS_IOS)
178
179 #if BUILDFLAG(IS_ANDROID)
Abort()180 void CurrentUIThread::Abort() {
181 GetMessagePumpForUI()->Abort();
182 }
183 #endif // BUILDFLAG(IS_ANDROID)
184
185 #if BUILDFLAG(IS_WIN)
AddMessagePumpObserver(MessagePumpForUI::Observer * observer)186 void CurrentUIThread::AddMessagePumpObserver(
187 MessagePumpForUI::Observer* observer) {
188 GetMessagePumpForUI()->AddObserver(observer);
189 }
190
RemoveMessagePumpObserver(MessagePumpForUI::Observer * observer)191 void CurrentUIThread::RemoveMessagePumpObserver(
192 MessagePumpForUI::Observer* observer) {
193 GetMessagePumpForUI()->RemoveObserver(observer);
194 }
195 #endif // BUILDFLAG(IS_WIN)
196
197 #endif // !BUILDFLAG(IS_NACL)
198
199 //------------------------------------------------------------------------------
200 // CurrentIOThread
201
202 // static
Get()203 CurrentIOThread CurrentIOThread::Get() {
204 auto* sequence_manager = GetCurrentSequenceManagerImpl();
205 DCHECK(sequence_manager);
206 DCHECK(sequence_manager->IsType(MessagePumpType::IO));
207 return CurrentIOThread(sequence_manager);
208 }
209
210 // static
IsSet()211 bool CurrentIOThread::IsSet() {
212 auto* sequence_manager = GetCurrentSequenceManagerImpl();
213 return sequence_manager && sequence_manager->IsType(MessagePumpType::IO);
214 }
215
GetMessagePumpForIO() const216 MessagePumpForIO* CurrentIOThread::GetMessagePumpForIO() const {
217 return static_cast<MessagePumpForIO*>(current_->GetMessagePump());
218 }
219
220 #if !BUILDFLAG(IS_NACL)
221
222 #if BUILDFLAG(IS_WIN)
RegisterIOHandler(HANDLE file,MessagePumpForIO::IOHandler * handler)223 bool CurrentIOThread::RegisterIOHandler(HANDLE file,
224 MessagePumpForIO::IOHandler* handler) {
225 DCHECK(current_->IsBoundToCurrentThread());
226 return GetMessagePumpForIO()->RegisterIOHandler(file, handler);
227 }
228
RegisterJobObject(HANDLE job,MessagePumpForIO::IOHandler * handler)229 bool CurrentIOThread::RegisterJobObject(HANDLE job,
230 MessagePumpForIO::IOHandler* handler) {
231 DCHECK(current_->IsBoundToCurrentThread());
232 return GetMessagePumpForIO()->RegisterJobObject(job, handler);
233 }
234
235 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForIO::Mode mode,MessagePumpForIO::FdWatchController * controller,MessagePumpForIO::FdWatcher * delegate)236 bool CurrentIOThread::WatchFileDescriptor(
237 int fd,
238 bool persistent,
239 MessagePumpForIO::Mode mode,
240 MessagePumpForIO::FdWatchController* controller,
241 MessagePumpForIO::FdWatcher* delegate) {
242 DCHECK(current_->IsBoundToCurrentThread());
243 return GetMessagePumpForIO()->WatchFileDescriptor(fd, persistent, mode,
244 controller, delegate);
245 }
246 #endif // BUILDFLAG(IS_WIN)
247
248 #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
WatchMachReceivePort(mach_port_t port,MessagePumpForIO::MachPortWatchController * controller,MessagePumpForIO::MachPortWatcher * delegate)249 bool CurrentIOThread::WatchMachReceivePort(
250 mach_port_t port,
251 MessagePumpForIO::MachPortWatchController* controller,
252 MessagePumpForIO::MachPortWatcher* delegate) {
253 DCHECK(current_->IsBoundToCurrentThread());
254 return GetMessagePumpForIO()->WatchMachReceivePort(port, controller,
255 delegate);
256 }
257 #endif
258
259 #endif // !BUILDFLAG(IS_NACL)
260
261 #if BUILDFLAG(IS_FUCHSIA)
262 // Additional watch API for native platform resources.
WatchZxHandle(zx_handle_t handle,bool persistent,zx_signals_t signals,MessagePumpForIO::ZxHandleWatchController * controller,MessagePumpForIO::ZxHandleWatcher * delegate)263 bool CurrentIOThread::WatchZxHandle(
264 zx_handle_t handle,
265 bool persistent,
266 zx_signals_t signals,
267 MessagePumpForIO::ZxHandleWatchController* controller,
268 MessagePumpForIO::ZxHandleWatcher* delegate) {
269 DCHECK(current_->IsBoundToCurrentThread());
270 return GetMessagePumpForIO()->WatchZxHandle(handle, persistent, signals,
271 controller, delegate);
272 }
273 #endif
274
275 } // namespace base
276