• 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 "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