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