summaryrefslogtreecommitdiff
path: root/base/message_loop/message_loop.cc
diff options
context:
space:
mode:
authorGabriel Charette <gab@chromium.org>2018-04-14 05:29:35 +0900
committerQijiang Fan <fqj@google.com>2020-06-05 09:03:58 +0900
commit393d94904f5919fb4a4202862985365b3e50106c (patch)
tree6eddc64cf07379cc619a621af01dd20ca2e9a877 /base/message_loop/message_loop.cc
parent1cf27fa44f42f83b11e837f5f40ced0afa8c2153 (diff)
downloadlibchrome-393d94904f5919fb4a4202862985365b3e50106c.tar.gz
Introduce base::MessageLoopCurrent
It extracts the statically accessible interface of MessageLoop (through MessageLoop::current()) from its core interface. See message_loop_current.h for more details. Note: At first it seemed like the easiest approach would have been to introduce MessageLoopInterface as the public interface which MessageLoop implements (and only return an interface pointer from current()). But that doesn't work once we get in MessageLoopForUI (and ForIO) territory as it would need to both be a MessageLoop (MessageLoop is-a MessageLoopInterface) and a MessageLoopInterfaceForUI (MessageLoopInterfaceForUI is-a MessageLoopInterface) and we have diamond inheritance... This thus enforces the current approach of MessageLoopCurrent being a separate class that merely represents a MessageLoop*. I think this is cleaner overall as well because it will allow must callers to include solely message_loop_current.h and ultimately have very few files including the message_loop.h impl (I'll also move MessageLoop::current() to MessageLoopCurrent::Get() in a follow-up). This CL adds many temporary implicit back-and-forth casts. After landing this, I plan to script migrations of the actual usage to the proper types with the goal of eventually disconnecting the two APIs (so that few callers actually need message_loop.h anymore and it's obvious what a replacement of MessageLoop needs to provide statically and/or what we need to deprecate before making such a move). This CL is a contract with the reviewer that I will follow-up with many TBRed CLs for trivial mass renames. Even though the implicit casts might not seem like this CL does much overall, it still required 25 precursor CLs (ref. crbug.com/825327) and landing this CL locks in those gains. Removed the two TestWatchingFromBadThread tests which are irrelevant now that going through MessageLoopForIOCurrent enforces usage on same thread via a ThreadChecker. NOPRESUBMIT=True (calls to deprecated MessageLoop methods) Bug: 825327 Change-Id: Ie66a394d02a162289aabe155436a583bfb024e8d Reviewed-on: https://chromium-review.googlesource.com/957760 Commit-Queue: Gabriel Charette <gab@chromium.org> Reviewed-by: kylechar <kylechar@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Cr-Commit-Position: refs/heads/master@{#550745} CrOS-Libchrome-Original-Commit: 01b8301844e2f1f6b282298f893b3a490e0828f4
Diffstat (limited to 'base/message_loop/message_loop.cc')
-rw-r--r--base/message_loop/message_loop.cc198
1 files changed, 69 insertions, 129 deletions
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index b417f2fffe..d84fb77921 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -12,7 +12,9 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_pump_default.h"
+#include "base/message_loop/message_pump_for_io.h"
#include "base/message_loop/message_pump_for_ui.h"
+#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread_id_name_manager.h"
@@ -31,8 +33,8 @@ namespace {
// A lazily created thread local storage for quick access to a thread's message
// loop, if one exists.
base::ThreadLocalPointer<MessageLoop>* GetTLSMessageLoop() {
- static auto* lazy_tls_ptr = new base::ThreadLocalPointer<MessageLoop>();
- return lazy_tls_ptr;
+ static NoDestructor<ThreadLocalPointer<MessageLoop>> lazy_tls_ptr;
+ return lazy_tls_ptr.get();
}
MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = nullptr;
@@ -44,14 +46,6 @@ std::unique_ptr<MessagePump> ReturnPump(std::unique_ptr<MessagePump> pump) {
//------------------------------------------------------------------------------
-MessageLoop::TaskObserver::TaskObserver() = default;
-
-MessageLoop::TaskObserver::~TaskObserver() = default;
-
-MessageLoop::DestructionObserver::~DestructionObserver() = default;
-
-//------------------------------------------------------------------------------
-
MessageLoop::MessageLoop(Type type)
: MessageLoop(type, MessagePumpFactoryCallback()) {
BindToCurrentThread();
@@ -67,7 +61,8 @@ MessageLoop::~MessageLoop() {
// current one on this thread. Otherwise, this loop is being destructed before
// it was bound to a thread, so a different message loop (or no loop at all)
// may be current.
- DCHECK((pump_ && current() == this) || (!pump_ && current() != this));
+ DCHECK((pump_ && GetTLSMessageLoop()->Get() == this) ||
+ (!pump_ && GetTLSMessageLoop()->Get() != this));
// iOS just attaches to the loop, it doesn't Run it.
// TODO(stuartmorgan): Consider wiring up a Detach().
@@ -75,7 +70,8 @@ MessageLoop::~MessageLoop() {
// There should be no active RunLoops on this thread, unless this MessageLoop
// isn't bound to the current thread (see other condition at the top of this
// method).
- DCHECK((!pump_ && current() != this) || !RunLoop::IsRunningOnCurrentThread());
+ DCHECK((!pump_ && GetTLSMessageLoop()->Get() != this) ||
+ !RunLoop::IsRunningOnCurrentThread());
#endif
#if defined(OS_WIN)
@@ -111,16 +107,13 @@ MessageLoop::~MessageLoop() {
task_runner_ = nullptr;
// OK, now make it so that no one can find us.
- if (current() == this)
+ if (GetTLSMessageLoop()->Get() == this)
GetTLSMessageLoop()->Set(nullptr);
}
// static
-MessageLoop* MessageLoop::current() {
- // TODO(darin): sadly, we cannot enable this yet since people call us even
- // when they have no intention of using us.
- // DCHECK(loop) << "Ouch, did you forget to initialize me?";
- return GetTLSMessageLoop()->Get();
+MessageLoopCurrent MessageLoop::current() {
+ return MessageLoopCurrent(GetTLSMessageLoop()->Get());
}
// static
@@ -166,50 +159,20 @@ std::unique_ptr<MessagePump> MessageLoop::CreateMessagePumpForType(Type type) {
#endif
}
-void MessageLoop::AddDestructionObserver(
- DestructionObserver* destruction_observer) {
- DCHECK_EQ(this, current());
- destruction_observers_.AddObserver(destruction_observer);
-}
-
-void MessageLoop::RemoveDestructionObserver(
- DestructionObserver* destruction_observer) {
- DCHECK_EQ(this, current());
- destruction_observers_.RemoveObserver(destruction_observer);
-}
-
bool MessageLoop::IsType(Type type) const {
return type_ == type;
}
-// static
-Closure MessageLoop::QuitWhenIdleClosure() {
- return Bind(&RunLoop::QuitCurrentWhenIdleDeprecated);
-}
-
-void MessageLoop::SetNestableTasksAllowed(bool allowed) {
- if (allowed) {
- // Kick the native pump just in case we enter a OS-driven nested message
- // loop that does not go through RunLoop::Run().
- pump_->ScheduleWork();
- }
- task_execution_allowed_ = allowed;
-}
-
-bool MessageLoop::NestableTasksAllowed() const {
- return task_execution_allowed_;
-}
-
// TODO(gab): Migrate TaskObservers to RunLoop as part of separating concerns
// between MessageLoop and RunLoop and making MessageLoop a swappable
// implementation detail. http://crbug.com/703346
void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
task_observers_.AddObserver(task_observer);
}
void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
task_observers_.RemoveObserver(task_observer);
}
@@ -237,7 +200,8 @@ std::unique_ptr<MessageLoop> MessageLoop::CreateUnbound(
}
MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory)
- : type_(type),
+ : MessageLoopCurrent(this),
+ type_(type),
pump_factory_(std::move(pump_factory)),
incoming_task_queue_(new internal::IncomingTaskQueue(this)),
unbound_task_runner_(
@@ -245,16 +209,22 @@ MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory)
task_runner_(unbound_task_runner_) {
// If type is TYPE_CUSTOM non-null pump_factory must be given.
DCHECK(type_ != TYPE_CUSTOM || !pump_factory_.is_null());
+
+ // Bound in BindToCurrentThread();
+ DETACH_FROM_THREAD(bound_thread_checker_);
}
void MessageLoop::BindToCurrentThread() {
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
+
DCHECK(!pump_);
if (!pump_factory_.is_null())
pump_ = std::move(pump_factory_).Run();
else
pump_ = CreateMessagePumpForType(type_);
- DCHECK(!current()) << "should only have one message loop per thread";
+ DCHECK(!GetTLSMessageLoop()->Get())
+ << "should only have one message loop per thread";
GetTLSMessageLoop()->Set(this);
incoming_task_queue_->StartScheduling();
@@ -279,7 +249,8 @@ std::string MessageLoop::GetThreadName() const {
void MessageLoop::SetTaskRunner(
scoped_refptr<SingleThreadTaskRunner> task_runner) {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
+
DCHECK(task_runner);
DCHECK(task_runner->BelongsToCurrentThread());
DCHECK(!unbound_task_runner_);
@@ -288,14 +259,15 @@ void MessageLoop::SetTaskRunner(
}
void MessageLoop::ClearTaskRunnerForTesting() {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
+
DCHECK(!unbound_task_runner_);
task_runner_ = nullptr;
thread_task_runner_handle_.reset();
}
void MessageLoop::Run(bool application_tasks_allowed) {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
if (application_tasks_allowed && !task_execution_allowed_) {
// Allow nested task execution as explicitly requested.
DCHECK(RunLoop::IsNestedOnCurrentThread());
@@ -308,18 +280,18 @@ void MessageLoop::Run(bool application_tasks_allowed) {
}
void MessageLoop::Quit() {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
pump_->Quit();
}
void MessageLoop::EnsureWorkScheduled() {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
if (incoming_task_queue_->triage_tasks().HasTasks())
pump_->ScheduleWork();
}
void MessageLoop::SetThreadTaskRunnerHandle() {
- DCHECK_EQ(this, current());
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
// Clear the previous thread task runner first, because only one can exist at
// a time.
thread_task_runner_handle_.reset();
@@ -471,102 +443,70 @@ bool MessageLoop::DoIdleWork() {
}
#if !defined(OS_NACL)
+
//------------------------------------------------------------------------------
// MessageLoopForUI
MessageLoopForUI::MessageLoopForUI(std::unique_ptr<MessagePump> pump)
: MessageLoop(TYPE_UI, BindOnce(&ReturnPump, std::move(pump))) {}
+// static
+MessageLoopCurrentForUI MessageLoopForUI::current() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ DCHECK(loop);
#if defined(OS_ANDROID)
-void MessageLoopForUI::Start() {
- // No Histogram support for UI message loop as it is managed by Java side
- static_cast<MessagePumpForUI*>(pump_.get())->Start(this);
+ DCHECK(loop->IsType(MessageLoop::TYPE_UI) ||
+ loop->IsType(MessageLoop::TYPE_JAVA));
+#else
+ DCHECK(loop->IsType(MessageLoop::TYPE_UI));
+#endif
+ auto* loop_for_ui = static_cast<MessageLoopForUI*>(loop);
+ return MessageLoopCurrentForUI(
+ loop_for_ui, static_cast<MessagePumpForUI*>(loop_for_ui->pump_.get()));
}
-void MessageLoopForUI::Abort() {
- static_cast<MessagePumpForUI*>(pump_.get())->Abort();
+// static
+bool MessageLoopForUI::IsCurrent() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ return loop && loop->IsType(MessageLoop::TYPE_UI);
}
-#endif
#if defined(OS_IOS)
void MessageLoopForUI::Attach() {
static_cast<MessagePumpUIApplication*>(pump_.get())->Attach(this);
}
-#endif
+#endif // defined(OS_IOS)
-#if (defined(USE_OZONE) && !defined(OS_FUCHSIA)) || \
- (defined(USE_X11) && !defined(USE_GLIB))
-bool MessageLoopForUI::WatchFileDescriptor(
- int fd,
- bool persistent,
- MessagePumpLibevent::Mode mode,
- MessagePumpLibevent::FdWatchController* controller,
- MessagePumpLibevent::FdWatcher* delegate) {
- return static_cast<MessagePumpForUI*>(pump_.get())
- ->WatchFileDescriptor(fd, persistent, mode, controller, delegate);
+#if defined(OS_ANDROID)
+void MessageLoopForUI::Start() {
+ // No Histogram support for UI message loop as it is managed by Java side
+ static_cast<MessagePumpForUI*>(pump_.get())->Start(this);
}
-#endif
+
+void MessageLoopForUI::Abort() {
+ static_cast<MessagePumpForUI*>(pump_.get())->Abort();
+}
+#endif // defined(OS_ANDROID)
#endif // !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopForIO
-#if !defined(OS_NACL_SFI)
-
-namespace {
-
-MessagePumpForIO* ToPumpIO(MessagePump* pump) {
- return static_cast<MessagePumpForIO*>(pump);
-}
-
-} // namespace
-
-#if defined(OS_WIN)
-void MessageLoopForIO::RegisterIOHandler(HANDLE file,
- MessagePumpForIO::IOHandler* handler) {
- ToPumpIO(pump_.get())->RegisterIOHandler(file, handler);
-}
-
-bool MessageLoopForIO::RegisterJobObject(HANDLE job,
- MessagePumpForIO::IOHandler* handler) {
- return ToPumpIO(pump_.get())->RegisterJobObject(job, handler);
-}
-
-bool MessageLoopForIO::WaitForIOCompletion(
- DWORD timeout,
- MessagePumpForIO::IOHandler* filter) {
- return ToPumpIO(pump_.get())->WaitForIOCompletion(timeout, filter);
-}
-#elif defined(OS_POSIX)
-bool MessageLoopForIO::WatchFileDescriptor(
- int fd,
- bool persistent,
- MessagePumpForIO::Mode mode,
- MessagePumpForIO::FdWatchController* controller,
- MessagePumpForIO::FdWatcher* delegate) {
- return ToPumpIO(pump_.get())->WatchFileDescriptor(
- fd,
- persistent,
- mode,
- controller,
- delegate);
+// static
+MessageLoopCurrentForIO MessageLoopForIO::current() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ DCHECK(loop);
+ DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
+ auto* loop_for_io = static_cast<MessageLoopForIO*>(loop);
+ return MessageLoopCurrentForIO(
+ loop_for_io, static_cast<MessagePumpForIO*>(loop_for_io->pump_.get()));
}
-#endif
-#endif // !defined(OS_NACL_SFI)
-
-#if defined(OS_FUCHSIA)
-// Additional watch API for native platform resources.
-bool MessageLoopForIO::WatchZxHandle(
- zx_handle_t handle,
- bool persistent,
- zx_signals_t signals,
- MessagePumpForIO::ZxHandleWatchController* controller,
- MessagePumpForIO::ZxHandleWatcher* delegate) {
- return ToPumpIO(pump_.get())
- ->WatchZxHandle(handle, persistent, signals, controller, delegate);
+// static
+bool MessageLoopForIO::IsCurrent() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ return loop && loop->IsType(MessageLoop::TYPE_IO);
}
-#endif
} // namespace base