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
operator ==(const CurrentThread & other) const113 bool CurrentThread::operator==(const CurrentThread& other) const {
114 return current_ == other.current_;
115 }
116
117 #if !BUILDFLAG(IS_NACL)
118
119 //------------------------------------------------------------------------------
120 // CurrentUIThread
121
122 // static
Get()123 CurrentUIThread CurrentUIThread::Get() {
124 auto* sequence_manager = GetCurrentSequenceManagerImpl();
125 DCHECK(sequence_manager);
126 #if BUILDFLAG(IS_ANDROID)
127 DCHECK(sequence_manager->IsType(MessagePumpType::UI) ||
128 sequence_manager->IsType(MessagePumpType::JAVA));
129 #else // BUILDFLAG(IS_ANDROID)
130 DCHECK(sequence_manager->IsType(MessagePumpType::UI));
131 #endif // BUILDFLAG(IS_ANDROID)
132 return CurrentUIThread(sequence_manager);
133 }
134
135 // static
IsSet()136 bool CurrentUIThread::IsSet() {
137 sequence_manager::internal::SequenceManagerImpl* sequence_manager =
138 GetCurrentSequenceManagerImpl();
139 return sequence_manager &&
140 #if BUILDFLAG(IS_ANDROID)
141 (sequence_manager->IsType(MessagePumpType::UI) ||
142 sequence_manager->IsType(MessagePumpType::JAVA));
143 #else // BUILDFLAG(IS_ANDROID)
144 sequence_manager->IsType(MessagePumpType::UI);
145 #endif // BUILDFLAG(IS_ANDROID)
146 }
147
GetMessagePumpForUI() const148 MessagePumpForUI* CurrentUIThread::GetMessagePumpForUI() const {
149 return static_cast<MessagePumpForUI*>(current_->GetMessagePump());
150 }
151
152 #if BUILDFLAG(IS_OZONE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForUI::Mode mode,MessagePumpForUI::FdWatchController * controller,MessagePumpForUI::FdWatcher * delegate)153 bool CurrentUIThread::WatchFileDescriptor(
154 int fd,
155 bool persistent,
156 MessagePumpForUI::Mode mode,
157 MessagePumpForUI::FdWatchController* controller,
158 MessagePumpForUI::FdWatcher* delegate) {
159 DCHECK(current_->IsBoundToCurrentThread());
160 return GetMessagePumpForUI()->WatchFileDescriptor(fd, persistent, mode,
161 controller, delegate);
162 }
163 #endif
164
165 #if BUILDFLAG(IS_IOS)
Attach()166 void CurrentUIThread::Attach() {
167 current_->AttachToMessagePump();
168 }
169 #endif // BUILDFLAG(IS_IOS)
170
171 #if BUILDFLAG(IS_ANDROID)
Abort()172 void CurrentUIThread::Abort() {
173 GetMessagePumpForUI()->Abort();
174 }
175 #endif // BUILDFLAG(IS_ANDROID)
176
177 #if BUILDFLAG(IS_WIN)
AddMessagePumpObserver(MessagePumpForUI::Observer * observer)178 void CurrentUIThread::AddMessagePumpObserver(
179 MessagePumpForUI::Observer* observer) {
180 GetMessagePumpForUI()->AddObserver(observer);
181 }
182
RemoveMessagePumpObserver(MessagePumpForUI::Observer * observer)183 void CurrentUIThread::RemoveMessagePumpObserver(
184 MessagePumpForUI::Observer* observer) {
185 GetMessagePumpForUI()->RemoveObserver(observer);
186 }
187 #endif // BUILDFLAG(IS_WIN)
188
189 #endif // !BUILDFLAG(IS_NACL)
190
191 //------------------------------------------------------------------------------
192 // CurrentIOThread
193
194 // static
Get()195 CurrentIOThread CurrentIOThread::Get() {
196 auto* sequence_manager = GetCurrentSequenceManagerImpl();
197 DCHECK(sequence_manager);
198 DCHECK(sequence_manager->IsType(MessagePumpType::IO));
199 return CurrentIOThread(sequence_manager);
200 }
201
202 // static
IsSet()203 bool CurrentIOThread::IsSet() {
204 auto* sequence_manager = GetCurrentSequenceManagerImpl();
205 return sequence_manager && sequence_manager->IsType(MessagePumpType::IO);
206 }
207
GetMessagePumpForIO() const208 MessagePumpForIO* CurrentIOThread::GetMessagePumpForIO() const {
209 return static_cast<MessagePumpForIO*>(current_->GetMessagePump());
210 }
211
212 #if !BUILDFLAG(IS_NACL)
213
214 #if BUILDFLAG(IS_WIN)
RegisterIOHandler(HANDLE file,MessagePumpForIO::IOHandler * handler)215 HRESULT CurrentIOThread::RegisterIOHandler(
216 HANDLE file,
217 MessagePumpForIO::IOHandler* handler) {
218 DCHECK(current_->IsBoundToCurrentThread());
219 return GetMessagePumpForIO()->RegisterIOHandler(file, handler);
220 }
221
RegisterJobObject(HANDLE job,MessagePumpForIO::IOHandler * handler)222 bool CurrentIOThread::RegisterJobObject(HANDLE job,
223 MessagePumpForIO::IOHandler* handler) {
224 DCHECK(current_->IsBoundToCurrentThread());
225 return GetMessagePumpForIO()->RegisterJobObject(job, handler);
226 }
227
228 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
WatchFileDescriptor(int fd,bool persistent,MessagePumpForIO::Mode mode,MessagePumpForIO::FdWatchController * controller,MessagePumpForIO::FdWatcher * delegate)229 bool CurrentIOThread::WatchFileDescriptor(
230 int fd,
231 bool persistent,
232 MessagePumpForIO::Mode mode,
233 MessagePumpForIO::FdWatchController* controller,
234 MessagePumpForIO::FdWatcher* delegate) {
235 DCHECK(current_->IsBoundToCurrentThread());
236 return GetMessagePumpForIO()->WatchFileDescriptor(fd, persistent, mode,
237 controller, delegate);
238 }
239 #endif // BUILDFLAG(IS_WIN)
240
241 #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
WatchMachReceivePort(mach_port_t port,MessagePumpForIO::MachPortWatchController * controller,MessagePumpForIO::MachPortWatcher * delegate)242 bool CurrentIOThread::WatchMachReceivePort(
243 mach_port_t port,
244 MessagePumpForIO::MachPortWatchController* controller,
245 MessagePumpForIO::MachPortWatcher* delegate) {
246 DCHECK(current_->IsBoundToCurrentThread());
247 return GetMessagePumpForIO()->WatchMachReceivePort(port, controller,
248 delegate);
249 }
250 #endif
251
252 #endif // !BUILDFLAG(IS_NACL)
253
254 #if BUILDFLAG(IS_FUCHSIA)
255 // Additional watch API for native platform resources.
WatchZxHandle(zx_handle_t handle,bool persistent,zx_signals_t signals,MessagePumpForIO::ZxHandleWatchController * controller,MessagePumpForIO::ZxHandleWatcher * delegate)256 bool CurrentIOThread::WatchZxHandle(
257 zx_handle_t handle,
258 bool persistent,
259 zx_signals_t signals,
260 MessagePumpForIO::ZxHandleWatchController* controller,
261 MessagePumpForIO::ZxHandleWatcher* delegate) {
262 DCHECK(current_->IsBoundToCurrentThread());
263 return GetMessagePumpForIO()->WatchZxHandle(handle, persistent, signals,
264 controller, delegate);
265 }
266 #endif
267
268 } // namespace base
269