1 // Copyright 2018 The Chromium Authors. All rights reserved. 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/message_loop/message_loop_current.h" 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_pump_for_io.h" 10 #include "base/message_loop/message_pump_for_ui.h" 11 #include "base/no_destructor.h" 12 #include "base/threading/thread_local.h" 13 14 namespace base { 15 16 namespace { 17 18 base::ThreadLocalPointer<MessageLoop>* GetTLSMessageLoop() { 19 static NoDestructor<ThreadLocalPointer<MessageLoop>> lazy_tls_ptr; 20 return lazy_tls_ptr.get(); 21 } 22 23 } // namespace 24 25 //------------------------------------------------------------------------------ 26 // MessageLoopCurrent 27 28 // static 29 MessageLoopCurrent MessageLoopCurrent::Get() { 30 return MessageLoopCurrent(GetTLSMessageLoop()->Get()); 31 } 32 33 // static 34 bool MessageLoopCurrent::IsSet() { 35 return !!GetTLSMessageLoop()->Get(); 36 } 37 38 void MessageLoopCurrent::AddDestructionObserver( 39 DestructionObserver* destruction_observer) { 40 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 41 current_->destruction_observers_.AddObserver(destruction_observer); 42 } 43 44 void MessageLoopCurrent::RemoveDestructionObserver( 45 DestructionObserver* destruction_observer) { 46 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 47 current_->destruction_observers_.RemoveObserver(destruction_observer); 48 } 49 50 const scoped_refptr<SingleThreadTaskRunner>& MessageLoopCurrent::task_runner() 51 const { 52 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 53 return current_->task_runner(); 54 } 55 56 void MessageLoopCurrent::SetTaskRunner( 57 scoped_refptr<SingleThreadTaskRunner> task_runner) { 58 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 59 current_->SetTaskRunner(std::move(task_runner)); 60 } 61 62 bool MessageLoopCurrent::IsIdleForTesting() { 63 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 64 return current_->IsIdleForTesting(); 65 } 66 67 void MessageLoopCurrent::AddTaskObserver(TaskObserver* task_observer) { 68 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 69 current_->AddTaskObserver(task_observer); 70 } 71 72 void MessageLoopCurrent::RemoveTaskObserver(TaskObserver* task_observer) { 73 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 74 current_->RemoveTaskObserver(task_observer); 75 } 76 77 void MessageLoopCurrent::SetNestableTasksAllowed(bool allowed) { 78 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 79 if (allowed) { 80 // Kick the native pump just in case we enter a OS-driven nested message 81 // loop that does not go through RunLoop::Run(). 82 current_->pump_->ScheduleWork(); 83 } 84 current_->task_execution_allowed_ = allowed; 85 } 86 87 bool MessageLoopCurrent::NestableTasksAllowed() const { 88 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 89 return current_->task_execution_allowed_; 90 } 91 92 MessageLoopCurrent::ScopedNestableTaskAllower::ScopedNestableTaskAllower() 93 : loop_(GetTLSMessageLoop()->Get()), 94 old_state_(loop_->NestableTasksAllowed()) { 95 loop_->SetNestableTasksAllowed(true); 96 } 97 98 MessageLoopCurrent::ScopedNestableTaskAllower::~ScopedNestableTaskAllower() { 99 loop_->SetNestableTasksAllowed(old_state_); 100 } 101 102 // static 103 void MessageLoopCurrent::BindToCurrentThreadInternal(MessageLoop* current) { 104 DCHECK(!GetTLSMessageLoop()->Get()) 105 << "Can't register a second MessageLoop on the same thread."; 106 GetTLSMessageLoop()->Set(current); 107 } 108 109 // static 110 void MessageLoopCurrent::UnbindFromCurrentThreadInternal(MessageLoop* current) { 111 DCHECK_EQ(current, GetTLSMessageLoop()->Get()); 112 GetTLSMessageLoop()->Set(nullptr); 113 } 114 115 bool MessageLoopCurrent::IsBoundToCurrentThreadInternal( 116 MessageLoop* message_loop) { 117 return GetTLSMessageLoop()->Get() == message_loop; 118 } 119 120 #if !defined(OS_NACL) 121 122 //------------------------------------------------------------------------------ 123 // MessageLoopCurrentForUI 124 125 // static 126 MessageLoopCurrentForUI MessageLoopCurrentForUI::Get() { 127 MessageLoop* loop = GetTLSMessageLoop()->Get(); 128 DCHECK(loop); 129 #if defined(OS_ANDROID) 130 DCHECK(loop->IsType(MessageLoop::TYPE_UI) || 131 loop->IsType(MessageLoop::TYPE_JAVA)); 132 #else // defined(OS_ANDROID) 133 DCHECK(loop->IsType(MessageLoop::TYPE_UI)); 134 #endif // defined(OS_ANDROID) 135 auto* loop_for_ui = static_cast<MessageLoopForUI*>(loop); 136 return MessageLoopCurrentForUI( 137 loop_for_ui, static_cast<MessagePumpForUI*>(loop_for_ui->pump_.get())); 138 } 139 140 // static 141 bool MessageLoopCurrentForUI::IsSet() { 142 MessageLoop* loop = GetTLSMessageLoop()->Get(); 143 return loop && 144 #if defined(OS_ANDROID) 145 (loop->IsType(MessageLoop::TYPE_UI) || 146 loop->IsType(MessageLoop::TYPE_JAVA)); 147 #else // defined(OS_ANDROID) 148 loop->IsType(MessageLoop::TYPE_UI); 149 #endif // defined(OS_ANDROID) 150 } 151 152 #if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN) 153 bool MessageLoopCurrentForUI::WatchFileDescriptor( 154 int fd, 155 bool persistent, 156 MessagePumpForUI::Mode mode, 157 MessagePumpForUI::FdWatchController* controller, 158 MessagePumpForUI::FdWatcher* delegate) { 159 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 160 return pump_->WatchFileDescriptor(fd, persistent, mode, controller, delegate); 161 } 162 #endif 163 164 #if defined(OS_IOS) 165 void MessageLoopCurrentForUI::Attach() { 166 static_cast<MessageLoopForUI*>(current_)->Attach(); 167 } 168 #endif // defined(OS_IOS) 169 170 #if defined(OS_ANDROID) 171 void MessageLoopCurrentForUI::Abort() { 172 static_cast<MessageLoopForUI*>(current_)->Abort(); 173 } 174 #endif // defined(OS_ANDROID) 175 176 #endif // !defined(OS_NACL) 177 178 //------------------------------------------------------------------------------ 179 // MessageLoopCurrentForIO 180 181 // static 182 MessageLoopCurrentForIO MessageLoopCurrentForIO::Get() { 183 MessageLoop* loop = GetTLSMessageLoop()->Get(); 184 DCHECK(loop); 185 DCHECK_EQ(MessageLoop::TYPE_IO, loop->type()); 186 auto* loop_for_io = static_cast<MessageLoopForIO*>(loop); 187 return MessageLoopCurrentForIO( 188 loop_for_io, static_cast<MessagePumpForIO*>(loop_for_io->pump_.get())); 189 } 190 191 // static 192 bool MessageLoopCurrentForIO::IsSet() { 193 MessageLoop* loop = GetTLSMessageLoop()->Get(); 194 return loop && loop->IsType(MessageLoop::TYPE_IO); 195 } 196 197 #if !defined(OS_NACL_SFI) 198 199 #if defined(OS_WIN) 200 HRESULT MessageLoopCurrentForIO::RegisterIOHandler( 201 HANDLE file, 202 MessagePumpForIO::IOHandler* handler) { 203 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 204 return pump_->RegisterIOHandler(file, handler); 205 } 206 207 bool MessageLoopCurrentForIO::RegisterJobObject( 208 HANDLE job, 209 MessagePumpForIO::IOHandler* handler) { 210 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 211 return pump_->RegisterJobObject(job, handler); 212 } 213 214 bool MessageLoopCurrentForIO::WaitForIOCompletion( 215 DWORD timeout, 216 MessagePumpForIO::IOHandler* filter) { 217 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 218 return pump_->WaitForIOCompletion(timeout, filter); 219 } 220 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 221 bool MessageLoopCurrentForIO::WatchFileDescriptor( 222 int fd, 223 bool persistent, 224 MessagePumpForIO::Mode mode, 225 MessagePumpForIO::FdWatchController* controller, 226 MessagePumpForIO::FdWatcher* delegate) { 227 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 228 return pump_->WatchFileDescriptor(fd, persistent, mode, controller, delegate); 229 } 230 #endif // defined(OS_WIN) 231 232 #endif // !defined(OS_NACL_SFI) 233 234 #if defined(OS_FUCHSIA) 235 // Additional watch API for native platform resources. 236 bool MessageLoopCurrentForIO::WatchZxHandle( 237 zx_handle_t handle, 238 bool persistent, 239 zx_signals_t signals, 240 MessagePumpForIO::ZxHandleWatchController* controller, 241 MessagePumpForIO::ZxHandleWatcher* delegate) { 242 DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_); 243 return pump_->WatchZxHandle(handle, persistent, signals, controller, 244 delegate); 245 } 246 #endif 247 248 } // namespace base 249