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