• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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