Home | History | Annotate | Download | only in message_loop
      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