summaryrefslogtreecommitdiffstats
path: root/chromium/base/message_loop
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/base/message_loop
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/base/message_loop')
-rw-r--r--chromium/base/message_loop/message_loop.cc196
-rw-r--r--chromium/base/message_loop/message_loop.h234
-rw-r--r--chromium/base/message_loop/message_loop_current.cc252
-rw-r--r--chromium/base/message_loop/message_loop_current.h303
-rw-r--r--chromium/base/message_loop/message_loop_io_posix_unittest.cc39
-rw-r--r--chromium/base/message_loop/message_loop_task_runner_unittest.cc4
-rw-r--r--chromium/base/message_loop/message_loop_unittest.cc75
-rw-r--r--chromium/base/message_loop/message_pump_android.cc1
-rw-r--r--chromium/base/message_loop/message_pump_for_ui.h8
-rw-r--r--chromium/base/message_loop/message_pump_fuchsia.cc217
-rw-r--r--chromium/base/message_loop/message_pump_fuchsia.h51
-rw-r--r--chromium/base/message_loop/message_pump_glib_unittest.cc19
-rw-r--r--chromium/base/message_loop/message_pump_io_ios_unittest.cc28
-rw-r--r--chromium/base/message_loop/message_pump_libevent_unittest.cc27
-rw-r--r--chromium/base/message_loop/message_pump_mac.mm67
-rw-r--r--chromium/base/message_loop/message_pump_mac_unittest.mm3
-rw-r--r--chromium/base/message_loop/message_pump_perftest.cc1
-rw-r--r--chromium/base/message_loop/message_pump_win.cc15
-rw-r--r--chromium/base/message_loop/message_pump_win.h7
19 files changed, 942 insertions, 605 deletions
diff --git a/chromium/base/message_loop/message_loop.cc b/chromium/base/message_loop/message_loop.cc
index b417f2fffe8..97ed778d8f1 100644
--- a/chromium/base/message_loop/message_loop.cc
+++ b/chromium/base/message_loop/message_loop.cc
@@ -12,11 +12,11 @@
#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/run_loop.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread_id_name_manager.h"
-#include "base/threading/thread_local.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -28,12 +28,6 @@ namespace base {
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;
-}
MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = nullptr;
std::unique_ptr<MessagePump> ReturnPump(std::unique_ptr<MessagePump> pump) {
@@ -44,14 +38,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 +53,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_ && MessageLoopCurrent::IsBoundToCurrentThreadInternal(this)) ||
+ (!pump_ && !MessageLoopCurrent::IsBoundToCurrentThreadInternal(this)));
// iOS just attaches to the loop, it doesn't Run it.
// TODO(stuartmorgan): Consider wiring up a Detach().
@@ -75,8 +62,10 @@ 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());
-#endif
+ DCHECK(
+ (!pump_ && !MessageLoopCurrent::IsBoundToCurrentThreadInternal(this)) ||
+ !RunLoop::IsRunningOnCurrentThread());
+#endif // !defined(OS_IOS)
#if defined(OS_WIN)
if (in_high_res_mode_)
@@ -111,16 +100,13 @@ MessageLoop::~MessageLoop() {
task_runner_ = nullptr;
// OK, now make it so that no one can find us.
- if (current() == this)
- GetTLSMessageLoop()->Set(nullptr);
+ if (MessageLoopCurrent::IsBoundToCurrentThreadInternal(this))
+ MessageLoopCurrent::UnbindFromCurrentThreadInternal(this);
}
// 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::Get();
}
// static
@@ -166,50 +152,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 +193,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,17 +202,23 @@ 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";
- GetTLSMessageLoop()->Set(this);
+ DCHECK(!MessageLoopCurrent::IsSet())
+ << "should only have one message loop per thread";
+ MessageLoopCurrent::BindToCurrentThreadInternal(this);
incoming_task_queue_->StartScheduling();
unbound_task_runner_->BindToCurrentThread();
@@ -279,7 +242,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 +252,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 +273,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,12 +436,29 @@ 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() {
+ return MessageLoopCurrentForUI::Get();
+}
+
+// static
+bool MessageLoopForUI::IsCurrent() {
+ return MessageLoopCurrentForUI::IsSet();
+}
+
+#if defined(OS_IOS)
+void MessageLoopForUI::Attach() {
+ static_cast<MessagePumpUIApplication*>(pump_.get())->Attach(this);
+}
+#endif // defined(OS_IOS)
+
#if defined(OS_ANDROID)
void MessageLoopForUI::Start() {
// No Histogram support for UI message loop as it is managed by Java side
@@ -486,87 +468,27 @@ void MessageLoopForUI::Start() {
void MessageLoopForUI::Abort() {
static_cast<MessagePumpForUI*>(pump_.get())->Abort();
}
-#endif
+#endif // defined(OS_ANDROID)
-#if defined(OS_IOS)
-void MessageLoopForUI::Attach() {
- static_cast<MessagePumpUIApplication*>(pump_.get())->Attach(this);
+#if defined(OS_WIN)
+void MessageLoopForUI::EnableWmQuit() {
+ static_cast<MessagePumpForUI*>(pump_.get())->EnableWmQuit();
}
-#endif
-
-#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);
-}
-#endif
+#endif // defined(OS_WIN)
#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() {
+ return MessageLoopCurrentForIO::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() {
+ return MessageLoopCurrentForIO::IsSet();
}
-#endif
} // namespace base
diff --git a/chromium/base/message_loop/message_loop.h b/chromium/base/message_loop/message_loop.h
index 439d364fc54..bd191fd9779 100644
--- a/chromium/base/message_loop/message_loop.h
+++ b/chromium/base/message_loop/message_loop.h
@@ -13,18 +13,18 @@
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "base/message_loop/incoming_task_queue.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_loop_task_runner.h"
#include "base/message_loop/message_pump.h"
-#include "base/message_loop/message_pump_for_io.h"
-#include "base/message_loop/message_pump_for_ui.h"
#include "base/message_loop/timer_slack.h"
#include "base/observer_list.h"
#include "base/pending_task.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequence_local_storage_map.h"
+#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -41,6 +41,18 @@ class ThreadTaskRunnerHandle;
// time permits) and signals sent to a registered set of HANDLEs may also be
// processed.
//
+// The MessageLoop's API should only be used directly by its owner (and users
+// which the owner opts to share a MessageLoop* with). Other ways to access
+// subsets of the MessageLoop API:
+// - base::RunLoop : Drive the MessageLoop from the thread it's bound to.
+// - base::Thread/SequencedTaskRunnerHandle : Post back to the MessageLoop
+// from a task running on it.
+// - SequenceLocalStorageSlot : Bind external state to this MessageLoop.
+// - base::MessageLoopCurrent : Access statically exposed APIs of this
+// MessageLoop.
+// - Embedders may provide their own static accessors to post tasks on
+// specific loops (e.g. content::BrowserThreads).
+//
// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
// on the thread where the MessageLoop's Run method executes.
//
@@ -55,7 +67,7 @@ class ThreadTaskRunnerHandle;
// Sample workaround when inner task processing is needed:
// HRESULT hr;
// {
-// MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+// MessageLoopCurrent::ScopedNestableTaskAllower allow;
// hr = DoDragDrop(...); // Implicitly runs a modal message loop.
// }
// // Process |hr| (the result returned by DoDragDrop()).
@@ -63,9 +75,17 @@ class ThreadTaskRunnerHandle;
// Please be SURE your task is reentrant (nestable) and all global variables
// are stable and accessible before calling SetNestableTasksAllowed(true).
//
+// TODO(gab): MessageLoop doesn't need to be a MessageLoopCurrent once callers
+// that store MessageLoop::current() in a MessageLoop* variable have been
+// updated to use a MessageLoopCurrent variable.
class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
- public RunLoop::Delegate {
+ public RunLoop::Delegate,
+ public MessageLoopCurrent {
public:
+ // TODO(gab): Migrate usage of this class to MessageLoopCurrent and remove
+ // this forwarded declaration.
+ using DestructionObserver = MessageLoopCurrent::DestructionObserver;
+
// A MessageLoop has a particular type, which indicates the set of
// asynchronous events it may process in addition to tasks and timers.
//
@@ -108,8 +128,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
~MessageLoop() override;
- // Returns the MessageLoop object for the current thread, or null if none.
- static MessageLoop* current();
+ // TODO(gab): Mass migrate callers to MessageLoopCurrent::Get().
+ static MessageLoopCurrent current();
using MessagePumpFactory = std::unique_ptr<MessagePump>();
// Uses the given base::MessagePumpForUIFactory to override the default
@@ -121,35 +141,6 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
// value.
static std::unique_ptr<MessagePump> CreateMessagePumpForType(Type type);
- // A DestructionObserver is notified when the current MessageLoop is being
- // destroyed. These observers are notified prior to MessageLoop::current()
- // being changed to return NULL. This gives interested parties the chance to
- // do final cleanup that depends on the MessageLoop.
- //
- // NOTE: Any tasks posted to the MessageLoop during this notification will
- // not be run. Instead, they will be deleted.
- //
- class BASE_EXPORT DestructionObserver {
- public:
- virtual void WillDestroyCurrentMessageLoop() = 0;
-
- protected:
- virtual ~DestructionObserver();
- };
-
- // Add a DestructionObserver, which will start receiving notifications
- // immediately.
- void AddDestructionObserver(DestructionObserver* destruction_observer);
-
- // Remove a DestructionObserver. It is safe to call this method while a
- // DestructionObserver is receiving a notification callback.
- void RemoveDestructionObserver(DestructionObserver* destruction_observer);
-
- // Deprecated: use RunLoop instead.
- // Construct a Closure that will call QuitWhenIdle(). Useful to schedule an
- // arbitrary MessageLoop to QuitWhenIdle.
- static Closure QuitWhenIdleClosure();
-
// Set the timer slack for this message loop.
void SetTimerSlack(TimerSlack timer_slack) {
pump_->SetTimerSlack(timer_slack);
@@ -170,7 +161,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
std::string GetThreadName() const;
// Gets the TaskRunner associated with this message loop.
- const scoped_refptr<SingleThreadTaskRunner>& task_runner() {
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner() const {
return task_runner_;
}
@@ -185,72 +176,9 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
// Must be called on the thread to which the message loop is bound.
void ClearTaskRunnerForTesting();
- // Enables or disables the recursive task processing. This happens in the case
- // of recursive message loops. Some unwanted message loops may occur when
- // using common controls or printer functions. By default, recursive task
- // processing is disabled.
- //
- // Please use |ScopedNestableTaskAllower| instead of calling these methods
- // directly. In general, nestable message loops are to be avoided. They are
- // dangerous and difficult to get right, so please use with extreme caution.
- //
- // The specific case where tasks get queued is:
- // - The thread is running a message loop.
- // - It receives a task #1 and executes it.
- // - The task #1 implicitly starts a message loop, like a MessageBox in the
- // unit test. This can also be StartDoc or GetSaveFileName.
- // - The thread receives a task #2 before or while in this second message
- // loop.
- // - With NestableTasksAllowed set to true, the task #2 will run right away.
- // Otherwise, it will get executed right after task #1 completes at "thread
- // message loop level".
- //
- // DEPRECATED: Use RunLoop::Type on the relevant RunLoop instead of these
- // methods.
- // TODO(gab): Migrate usage and delete these methods.
- void SetNestableTasksAllowed(bool allowed);
- bool NestableTasksAllowed() const;
-
- // Enables nestable tasks on |loop| while in scope.
- // DEPRECATED: This should not be used when the nested loop is driven by
- // RunLoop (use RunLoop::Type::kNestableTasksAllowed instead). It can however
- // still be useful in a few scenarios where re-entrancy is caused by a native
- // message loop.
- // TODO(gab): Remove usage of this class alongside RunLoop and rename it to
- // ScopedApplicationTasksAllowedInNativeNestedLoop(?).
- class ScopedNestableTaskAllower {
- public:
- explicit ScopedNestableTaskAllower(MessageLoop* loop)
- : loop_(loop),
- old_state_(loop_->NestableTasksAllowed()) {
- loop_->SetNestableTasksAllowed(true);
- }
- ~ScopedNestableTaskAllower() {
- loop_->SetNestableTasksAllowed(old_state_);
- }
-
- private:
- MessageLoop* const loop_;
- const bool old_state_;
- };
-
- // A TaskObserver is an object that receives task notifications from the
- // MessageLoop.
- //
- // NOTE: A TaskObserver implementation should be extremely fast!
- class BASE_EXPORT TaskObserver {
- public:
- TaskObserver();
-
- // This method is called before processing a task.
- virtual void WillProcessTask(const PendingTask& pending_task) = 0;
-
- // This method is called after processing a task.
- virtual void DidProcessTask(const PendingTask& pending_task) = 0;
-
- protected:
- virtual ~TaskObserver();
- };
+ // TODO(https://crbug.com/825327): Remove users of TaskObservers through
+ // MessageLoop::current() and migrate the type back here.
+ using TaskObserver = MessageLoopCurrent::TaskObserver;
// These functions can only be called on the same thread that |this| is
// running on.
@@ -287,6 +215,9 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
private:
friend class internal::IncomingTaskQueue;
+ friend class MessageLoopCurrent;
+ friend class MessageLoopCurrentForIO;
+ friend class MessageLoopCurrentForUI;
friend class ScheduleWorkTest;
friend class Thread;
FRIEND_TEST_ALL_PREFIXES(MessageLoopTest, DeleteUnboundLoop);
@@ -385,6 +316,10 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
std::unique_ptr<internal::ScopedSetSequenceLocalStorageMapForCurrentThread>
scoped_set_sequence_local_storage_map_for_current_thread_;
+ // Verifies that calls are made on the thread on which BindToCurrentThread()
+ // was invoked.
+ THREAD_CHECKER(bound_thread_checker_);
+
DISALLOW_COPY_AND_ASSIGN(MessageLoop);
};
@@ -394,8 +329,11 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
// MessageLoopForUI extends MessageLoop with methods that are particular to a
// MessageLoop instantiated with TYPE_UI.
//
-// This class is typically used like so:
-// MessageLoopForUI::current()->...call some method...
+// By instantiating a MessageLoopForUI on the current thread, the owner enables
+// native UI message pumping.
+//
+// MessageLoopCurrentForUI is exposed statically on its thread via
+// MessageLoopCurrentForUI::Get() to provide additional functionality.
//
class BASE_EXPORT MessageLoopForUI : public MessageLoop {
public:
@@ -404,23 +342,9 @@ class BASE_EXPORT MessageLoopForUI : public MessageLoop {
explicit MessageLoopForUI(std::unique_ptr<MessagePump> pump);
- // Returns the MessageLoopForUI of the current thread.
- static MessageLoopForUI* current() {
- MessageLoop* loop = MessageLoop::current();
- DCHECK(loop);
-#if defined(OS_ANDROID)
- DCHECK(loop->IsType(MessageLoop::TYPE_UI) ||
- loop->IsType(MessageLoop::TYPE_JAVA));
-#else
- DCHECK(loop->IsType(MessageLoop::TYPE_UI));
-#endif
- return static_cast<MessageLoopForUI*>(loop);
- }
-
- static bool IsCurrent() {
- MessageLoop* loop = MessageLoop::current();
- return loop && loop->IsType(MessageLoop::TYPE_UI);
- }
+ // TODO(gab): Mass migrate callers to MessageLoopCurrentForUI::Get()/IsSet().
+ static MessageLoopCurrentForUI current();
+ static bool IsCurrent();
#if defined(OS_IOS)
// On iOS, the main message loop cannot be Run(). Instead call Attach(),
@@ -440,17 +364,9 @@ class BASE_EXPORT MessageLoopForUI : public MessageLoop {
void Abort();
#endif
-#if (defined(USE_OZONE) && !defined(OS_FUCHSIA)) || \
- (defined(USE_X11) && !defined(USE_GLIB))
- // Please see MessagePumpLibevent for definition.
- static_assert(std::is_same<MessagePumpForUI, MessagePumpLibevent>::value,
- "MessageLoopForUI::WatchFileDescriptor is not supported when "
- "MessagePumpForUI is not a MessagePumpLibevent.");
- bool WatchFileDescriptor(int fd,
- bool persistent,
- MessagePumpForUI::Mode mode,
- MessagePumpForUI::FdWatchController* controller,
- MessagePumpForUI::FdWatcher* delegate);
+#if defined(OS_WIN)
+ // See method of the same name in the Windows MessagePumpForUI implementation.
+ void EnableWmQuit();
#endif
};
@@ -466,53 +382,19 @@ static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
// MessageLoopForIO extends MessageLoop with methods that are particular to a
// MessageLoop instantiated with TYPE_IO.
//
-// This class is typically used like so:
-// MessageLoopForIO::current()->...call some method...
+// By instantiating a MessageLoopForIO on the current thread, the owner enables
+// native async IO message pumping.
+//
+// MessageLoopCurrentForIO is exposed statically on its thread via
+// MessageLoopCurrentForIO::Get() to provide additional functionality.
//
class BASE_EXPORT MessageLoopForIO : public MessageLoop {
public:
- MessageLoopForIO() : MessageLoop(TYPE_IO) {
- }
+ MessageLoopForIO() : MessageLoop(TYPE_IO) {}
- // Returns the MessageLoopForIO of the current thread.
- static MessageLoopForIO* current() {
- MessageLoop* loop = MessageLoop::current();
- DCHECK(loop);
- DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
- return static_cast<MessageLoopForIO*>(loop);
- }
-
- static bool IsCurrent() {
- MessageLoop* loop = MessageLoop::current();
- return loop && loop->type() == MessageLoop::TYPE_IO;
- }
-
-#if !defined(OS_NACL_SFI)
-
-#if defined(OS_WIN)
- // Please see MessagePumpWin for definitions of these methods.
- void RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler);
- bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler);
- bool WaitForIOCompletion(DWORD timeout, MessagePumpForIO::IOHandler* filter);
-#elif defined(OS_POSIX)
- // Please see WatchableIOMessagePumpPosix for definition.
- // Prefer base::FileDescriptorWatcher for non-critical IO.
- bool WatchFileDescriptor(int fd,
- bool persistent,
- MessagePumpForIO::Mode mode,
- MessagePumpForIO::FdWatchController* controller,
- MessagePumpForIO::FdWatcher* delegate);
-#endif // defined(OS_IOS) || defined(OS_POSIX)
-#endif // !defined(OS_NACL_SFI)
-
-#if defined(OS_FUCHSIA)
- // Additional watch API for native platform resources.
- bool WatchZxHandle(zx_handle_t handle,
- bool persistent,
- zx_signals_t signals,
- MessagePumpForIO::ZxHandleWatchController* controller,
- MessagePumpForIO::ZxHandleWatcher* delegate);
-#endif
+ // TODO(gab): Mass migrate callers to MessageLoopCurrentForIO::Get()/IsSet().
+ static MessageLoopCurrentForIO current();
+ static bool IsCurrent();
};
// Do not add any member variables to MessageLoopForIO! This is important b/c
diff --git a/chromium/base/message_loop/message_loop_current.cc b/chromium/base/message_loop/message_loop_current.cc
new file mode 100644
index 00000000000..0beef5ae0fc
--- /dev/null
+++ b/chromium/base/message_loop/message_loop_current.cc
@@ -0,0 +1,252 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop_current.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.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/threading/thread_local.h"
+
+namespace base {
+
+namespace {
+
+base::ThreadLocalPointer<MessageLoop>* GetTLSMessageLoop() {
+ static NoDestructor<ThreadLocalPointer<MessageLoop>> lazy_tls_ptr;
+ return lazy_tls_ptr.get();
+}
+
+} // namespace
+
+//------------------------------------------------------------------------------
+// MessageLoopCurrent
+
+// static
+MessageLoopCurrent MessageLoopCurrent::Get() {
+ return MessageLoopCurrent(GetTLSMessageLoop()->Get());
+}
+
+// static
+bool MessageLoopCurrent::IsSet() {
+ return !!GetTLSMessageLoop()->Get();
+}
+
+void MessageLoopCurrent::AddDestructionObserver(
+ DestructionObserver* destruction_observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ current_->destruction_observers_.AddObserver(destruction_observer);
+}
+
+void MessageLoopCurrent::RemoveDestructionObserver(
+ DestructionObserver* destruction_observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ current_->destruction_observers_.RemoveObserver(destruction_observer);
+}
+
+const scoped_refptr<SingleThreadTaskRunner>& MessageLoopCurrent::task_runner()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return current_->task_runner();
+}
+
+void MessageLoopCurrent::SetTaskRunner(
+ scoped_refptr<SingleThreadTaskRunner> task_runner) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ current_->SetTaskRunner(std::move(task_runner));
+}
+
+bool MessageLoopCurrent::IsIdleForTesting() {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return current_->IsIdleForTesting();
+}
+
+void MessageLoopCurrent::AddTaskObserver(TaskObserver* task_observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ current_->AddTaskObserver(task_observer);
+}
+
+void MessageLoopCurrent::RemoveTaskObserver(TaskObserver* task_observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ current_->RemoveTaskObserver(task_observer);
+}
+
+void MessageLoopCurrent::SetNestableTasksAllowed(bool allowed) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ if (allowed) {
+ // Kick the native pump just in case we enter a OS-driven nested message
+ // loop that does not go through RunLoop::Run().
+ current_->pump_->ScheduleWork();
+ }
+ current_->task_execution_allowed_ = allowed;
+}
+
+bool MessageLoopCurrent::NestableTasksAllowed() const {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return current_->task_execution_allowed_;
+}
+
+MessageLoopCurrent::ScopedNestableTaskAllower::ScopedNestableTaskAllower()
+ : loop_(GetTLSMessageLoop()->Get()),
+ old_state_(loop_->NestableTasksAllowed()) {
+ loop_->SetNestableTasksAllowed(true);
+}
+
+MessageLoopCurrent::ScopedNestableTaskAllower::~ScopedNestableTaskAllower() {
+ loop_->SetNestableTasksAllowed(old_state_);
+}
+
+// static
+void MessageLoopCurrent::BindToCurrentThreadInternal(MessageLoop* current) {
+ DCHECK(!GetTLSMessageLoop()->Get())
+ << "Can't register a second MessageLoop on the same thread.";
+ GetTLSMessageLoop()->Set(current);
+}
+
+// static
+void MessageLoopCurrent::UnbindFromCurrentThreadInternal(MessageLoop* current) {
+ DCHECK_EQ(current, GetTLSMessageLoop()->Get());
+ GetTLSMessageLoop()->Set(nullptr);
+}
+
+bool MessageLoopCurrent::IsBoundToCurrentThreadInternal(
+ MessageLoop* message_loop) {
+ return GetTLSMessageLoop()->Get() == message_loop;
+}
+
+#if !defined(OS_NACL)
+
+//------------------------------------------------------------------------------
+// MessageLoopCurrentForUI
+
+// static
+MessageLoopCurrentForUI MessageLoopCurrentForUI::Get() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ DCHECK(loop);
+#if defined(OS_ANDROID)
+ DCHECK(loop->IsType(MessageLoop::TYPE_UI) ||
+ loop->IsType(MessageLoop::TYPE_JAVA));
+#else // defined(OS_ANDROID)
+ DCHECK(loop->IsType(MessageLoop::TYPE_UI));
+#endif // defined(OS_ANDROID)
+ auto* loop_for_ui = static_cast<MessageLoopForUI*>(loop);
+ return MessageLoopCurrentForUI(
+ loop_for_ui, static_cast<MessagePumpForUI*>(loop_for_ui->pump_.get()));
+}
+
+// static
+bool MessageLoopCurrentForUI::IsSet() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ return loop &&
+#if defined(OS_ANDROID)
+ (loop->IsType(MessageLoop::TYPE_UI) ||
+ loop->IsType(MessageLoop::TYPE_JAVA));
+#else // defined(OS_ANDROID)
+ loop->IsType(MessageLoop::TYPE_UI);
+#endif // defined(OS_ANDROID)
+}
+
+#if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN)
+bool MessageLoopCurrentForUI::WatchFileDescriptor(
+ int fd,
+ bool persistent,
+ MessagePumpForUI::Mode mode,
+ MessagePumpForUI::FdWatchController* controller,
+ MessagePumpForUI::FdWatcher* delegate) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return pump_->WatchFileDescriptor(fd, persistent, mode, controller, delegate);
+}
+#endif
+
+#if defined(OS_IOS)
+void MessageLoopCurrentForUI::Attach() {
+ static_cast<MessageLoopForUI*>(current_)->Attach();
+}
+#endif // defined(OS_IOS)
+
+#if defined(OS_ANDROID)
+void MessageLoopCurrentForUI::Start() {
+ static_cast<MessageLoopForUI*>(current_)->Start();
+}
+
+void MessageLoopCurrentForUI::Abort() {
+ static_cast<MessageLoopForUI*>(current_)->Abort();
+}
+#endif // defined(OS_ANDROID)
+
+#endif // !defined(OS_NACL)
+
+//------------------------------------------------------------------------------
+// MessageLoopCurrentForIO
+
+// static
+MessageLoopCurrentForIO MessageLoopCurrentForIO::Get() {
+ 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()));
+}
+
+// static
+bool MessageLoopCurrentForIO::IsSet() {
+ MessageLoop* loop = GetTLSMessageLoop()->Get();
+ return loop && loop->IsType(MessageLoop::TYPE_IO);
+}
+
+#if !defined(OS_NACL_SFI)
+
+#if defined(OS_WIN)
+void MessageLoopCurrentForIO::RegisterIOHandler(
+ HANDLE file,
+ MessagePumpForIO::IOHandler* handler) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ pump_->RegisterIOHandler(file, handler);
+}
+
+bool MessageLoopCurrentForIO::RegisterJobObject(
+ HANDLE job,
+ MessagePumpForIO::IOHandler* handler) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return pump_->RegisterJobObject(job, handler);
+}
+
+bool MessageLoopCurrentForIO::WaitForIOCompletion(
+ DWORD timeout,
+ MessagePumpForIO::IOHandler* filter) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return pump_->WaitForIOCompletion(timeout, filter);
+}
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+bool MessageLoopCurrentForIO::WatchFileDescriptor(
+ int fd,
+ bool persistent,
+ MessagePumpForIO::Mode mode,
+ MessagePumpForIO::FdWatchController* controller,
+ MessagePumpForIO::FdWatcher* delegate) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return pump_->WatchFileDescriptor(fd, persistent, mode, controller, delegate);
+}
+#endif // defined(OS_WIN)
+
+#endif // !defined(OS_NACL_SFI)
+
+#if defined(OS_FUCHSIA)
+// Additional watch API for native platform resources.
+bool MessageLoopCurrentForIO::WatchZxHandle(
+ zx_handle_t handle,
+ bool persistent,
+ zx_signals_t signals,
+ MessagePumpForIO::ZxHandleWatchController* controller,
+ MessagePumpForIO::ZxHandleWatcher* delegate) {
+ DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
+ return pump_->WatchZxHandle(handle, persistent, signals, controller,
+ delegate);
+}
+#endif
+
+} // namespace base
diff --git a/chromium/base/message_loop/message_loop_current.h b/chromium/base/message_loop/message_loop_current.h
new file mode 100644
index 00000000000..c5016dcf20a
--- /dev/null
+++ b/chromium/base/message_loop/message_loop_current.h
@@ -0,0 +1,303 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
+
+#include "base/base_export.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_pump_for_io.h"
+#include "base/message_loop/message_pump_for_ui.h"
+#include "base/pending_task.h"
+#include "base/single_thread_task_runner.h"
+#include "build/build_config.h"
+
+namespace base {
+
+class MessageLoop;
+
+// MessageLoopCurrent is a proxy to the public interface of the MessageLoop
+// bound to the thread it's obtained on.
+//
+// MessageLoopCurrent(ForUI|ForIO) is available statically through
+// MessageLoopCurrent(ForUI|ForIO)::Get() on threads that have a matching
+// MessageLoop instance. APIs intended for all consumers on the thread should be
+// on MessageLoopCurrent(ForUI|ForIO), while APIs intended for the owner of the
+// instance should be on MessageLoop(ForUI|ForIO).
+//
+// Why: Historically MessageLoop::current() gave access to the full MessageLoop
+// API, preventing both addition of powerful owner-only APIs as well as making
+// it harder to remove callers of deprecated APIs (that need to stick around for
+// a few owner-only use cases and re-accrue callers after cleanup per remaining
+// publicly available).
+//
+// As such, many methods below are flagged as deprecated and should be removed
+// (or moved back to MessageLoop) once all static callers have been migrated.
+class BASE_EXPORT MessageLoopCurrent {
+ public:
+ // MessageLoopCurrent is effectively just a disguised pointer and is fine to
+ // copy around.
+ MessageLoopCurrent(const MessageLoopCurrent& other) = default;
+ MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = default;
+
+ // Returns a proxy object to interact with the MessageLoop running the
+ // current thread. It must only be used on the thread it was obtained.
+ static MessageLoopCurrent Get();
+
+ // Returns true if the current thread is running a MessageLoop. Prefer this to
+ // verifying the boolean value of Get() (so that Get() can ultimately DCHECK
+ // it's only invoked when IsSet()).
+ static bool IsSet();
+
+ // Allow MessageLoopCurrent to be used like a pointer to support the many
+ // callsites that used MessageLoop::current() that way when it was a
+ // MessageLoop*.
+ MessageLoopCurrent* operator->() { return this; }
+ explicit operator bool() const { return !!current_; }
+
+ // TODO(gab): Migrate the types of variables that store MessageLoop::current()
+ // and remove this implicit cast back to MessageLoop*.
+ operator MessageLoop*() const { return current_; }
+
+ // A DestructionObserver is notified when the current MessageLoop is being
+ // destroyed. These observers are notified prior to MessageLoop::current()
+ // being changed to return NULL. This gives interested parties the chance to
+ // do final cleanup that depends on the MessageLoop.
+ //
+ // NOTE: Any tasks posted to the MessageLoop during this notification will
+ // not be run. Instead, they will be deleted.
+ //
+ // Deprecation note: Prefer SequenceLocalStorageSlot<std::unique_ptr<Foo>> to
+ // DestructionObserver to bind an object's lifetime to the current
+ // thread/sequence.
+ class BASE_EXPORT DestructionObserver {
+ public:
+ virtual void WillDestroyCurrentMessageLoop() = 0;
+
+ protected:
+ virtual ~DestructionObserver() = default;
+ };
+
+ // Add a DestructionObserver, which will start receiving notifications
+ // immediately.
+ void AddDestructionObserver(DestructionObserver* destruction_observer);
+
+ // Remove a DestructionObserver. It is safe to call this method while a
+ // DestructionObserver is receiving a notification callback.
+ void RemoveDestructionObserver(DestructionObserver* destruction_observer);
+
+ // Forwards to MessageLoop::task_runner().
+ // DEPRECATED(https://crbug.com/616447): Use ThreadTaskRunnerHandle::Get()
+ // instead of MessageLoopCurrent::Get()->task_runner().
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner() const;
+
+ // Forwards to MessageLoop::SetTaskRunner().
+ // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop
+ // instance should replace its TaskRunner.
+ void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
+
+ // A TaskObserver is an object that receives task notifications from the
+ // MessageLoop.
+ //
+ // NOTE: A TaskObserver implementation should be extremely fast!
+ class BASE_EXPORT TaskObserver {
+ public:
+ // This method is called before processing a task.
+ virtual void WillProcessTask(const PendingTask& pending_task) = 0;
+
+ // This method is called after processing a task.
+ virtual void DidProcessTask(const PendingTask& pending_task) = 0;
+
+ protected:
+ virtual ~TaskObserver() = default;
+ };
+
+ // Forwards to MessageLoop::(Add|Remove)TaskObserver.
+ // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop
+ // instance should add task observers on it.
+ void AddTaskObserver(TaskObserver* task_observer);
+ void RemoveTaskObserver(TaskObserver* task_observer);
+
+ // Enables or disables the recursive task processing. This happens in the case
+ // of recursive message loops. Some unwanted message loops may occur when
+ // using common controls or printer functions. By default, recursive task
+ // processing is disabled.
+ //
+ // Please use |ScopedNestableTaskAllower| instead of calling these methods
+ // directly. In general, nestable message loops are to be avoided. They are
+ // dangerous and difficult to get right, so please use with extreme caution.
+ //
+ // The specific case where tasks get queued is:
+ // - The thread is running a message loop.
+ // - It receives a task #1 and executes it.
+ // - The task #1 implicitly starts a message loop, like a MessageBox in the
+ // unit test. This can also be StartDoc or GetSaveFileName.
+ // - The thread receives a task #2 before or while in this second message
+ // loop.
+ // - With NestableTasksAllowed set to true, the task #2 will run right away.
+ // Otherwise, it will get executed right after task #1 completes at "thread
+ // message loop level".
+ //
+ // DEPRECATED(https://crbug.com/750779): Use RunLoop::Type on the relevant
+ // RunLoop instead of these methods.
+ // TODO(gab): Migrate usage and delete these methods.
+ void SetNestableTasksAllowed(bool allowed);
+ bool NestableTasksAllowed() const;
+
+ // Enables nestable tasks on the current MessageLoop while in scope.
+ // DEPRECATED(https://crbug.com/750779): This should not be used when the
+ // nested loop is driven by RunLoop (use RunLoop::Type::kNestableTasksAllowed
+ // instead). It can however still be useful in a few scenarios where re-
+ // entrancy is caused by a native message loop.
+ // TODO(gab): Remove usage of this class alongside RunLoop and rename it to
+ // ScopedApplicationTasksAllowedInNativeNestedLoop(?) for remaining use cases.
+ class BASE_EXPORT ScopedNestableTaskAllower {
+ public:
+ ScopedNestableTaskAllower();
+ ~ScopedNestableTaskAllower();
+
+ private:
+ MessageLoop* const loop_;
+ const bool old_state_;
+ };
+
+ // Returns true if the message loop is idle (ignoring delayed tasks). This is
+ // the same condition which triggers DoWork() to return false: i.e.
+ // out of tasks which can be processed at the current run-level -- there might
+ // be deferred non-nestable tasks remaining if currently in a nested run
+ // level.
+ bool IsIdleForTesting();
+
+ // Binds |current| to the current thread. It will from then on be the
+ // MessageLoop driven by MessageLoopCurrent on this thread. This is only meant
+ // to be invoked by the MessageLoop itself.
+ static void BindToCurrentThreadInternal(MessageLoop* current);
+
+ // Unbinds |current| from the current thread. Must be invoked on the same
+ // thread that invoked |BindToCurrentThreadInternal(current)|. This is only
+ // meant to be invoked by the MessageLoop itself.
+ static void UnbindFromCurrentThreadInternal(MessageLoop* current);
+
+ // Returns true if |message_loop| is bound to MessageLoopCurrent on the
+ // current thread. This is only meant to be invoked by the MessageLoop itself.
+ static bool IsBoundToCurrentThreadInternal(MessageLoop* message_loop);
+
+ protected:
+ explicit MessageLoopCurrent(MessageLoop* current) : current_(current) {}
+
+ MessageLoop* const current_;
+};
+
+#if !defined(OS_NACL)
+
+// ForUI extension of MessageLoopCurrent.
+class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent {
+ public:
+ // Returns an interface for the MessageLoopForUI of the current thread.
+ // Asserts that IsSet().
+ static MessageLoopCurrentForUI Get();
+
+ // Returns true if the current thread is running a MessageLoopForUI.
+ static bool IsSet();
+
+ MessageLoopCurrentForUI* operator->() { return this; }
+
+#if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN)
+ // Please see MessagePumpLibevent for definition.
+ static_assert(std::is_same<MessagePumpForUI, MessagePumpLibevent>::value,
+ "MessageLoopCurrentForUI::WatchFileDescriptor is not supported "
+ "when MessagePumpForUI is not a MessagePumpLibevent.");
+ bool WatchFileDescriptor(int fd,
+ bool persistent,
+ MessagePumpForUI::Mode mode,
+ MessagePumpForUI::FdWatchController* controller,
+ MessagePumpForUI::FdWatcher* delegate);
+#endif
+
+#if defined(OS_IOS)
+ // Forwards to MessageLoopForUI::Attach().
+ // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to
+ // callers and remove ability to access this method from
+ // MessageLoopCurrentForUI.
+ void Attach();
+#endif
+
+#if defined(OS_ANDROID)
+ // Forwards to MessageLoopForUI::Start().
+ // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to
+ // callers and remove ability to access this method from
+ // MessageLoopCurrentForUI.
+ void Start();
+
+ // Forwards to MessageLoopForUI::Abort().
+ // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to
+ // callers and remove ability to access this method from
+ // MessageLoopCurrentForUI.
+ void Abort();
+#endif
+
+ private:
+ MessageLoopCurrentForUI(MessageLoop* current, MessagePumpForUI* pump)
+ : MessageLoopCurrent(current), pump_(pump) {
+ DCHECK(pump_);
+ }
+
+ MessagePumpForUI* const pump_;
+};
+
+#endif // !defined(OS_NACL)
+
+// ForIO extension of MessageLoopCurrent.
+class BASE_EXPORT MessageLoopCurrentForIO : public MessageLoopCurrent {
+ public:
+ // Returns an interface for the MessageLoopForIO of the current thread.
+ // Asserts that IsSet().
+ static MessageLoopCurrentForIO Get();
+
+ // Returns true if the current thread is running a MessageLoopForIO.
+ static bool IsSet();
+
+ MessageLoopCurrentForIO* operator->() { return this; }
+
+#if !defined(OS_NACL_SFI)
+
+#if defined(OS_WIN)
+ // Please see MessagePumpWin for definitions of these methods.
+ void RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler);
+ bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler);
+ bool WaitForIOCompletion(DWORD timeout, MessagePumpForIO::IOHandler* filter);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+ // Please see WatchableIOMessagePumpPosix for definition.
+ // Prefer base::FileDescriptorWatcher for non-critical IO.
+ bool WatchFileDescriptor(int fd,
+ bool persistent,
+ MessagePumpForIO::Mode mode,
+ MessagePumpForIO::FdWatchController* controller,
+ MessagePumpForIO::FdWatcher* delegate);
+#endif // defined(OS_WIN)
+
+#if defined(OS_FUCHSIA)
+ // Additional watch API for native platform resources.
+ bool WatchZxHandle(zx_handle_t handle,
+ bool persistent,
+ zx_signals_t signals,
+ MessagePumpForIO::ZxHandleWatchController* controller,
+ MessagePumpForIO::ZxHandleWatcher* delegate);
+#endif // defined(OS_FUCHSIA)
+
+#endif // !defined(OS_NACL_SFI)
+
+ private:
+ MessageLoopCurrentForIO(MessageLoop* current, MessagePumpForIO* pump)
+ : MessageLoopCurrent(current), pump_(pump) {
+ DCHECK(pump_);
+ }
+
+ MessagePumpForIO* const pump_;
+};
+
+} // namespace base
+
+#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
diff --git a/chromium/base/message_loop/message_loop_io_posix_unittest.cc b/chromium/base/message_loop/message_loop_io_posix_unittest.cc
index 2c6d394bc86..4dd5f280280 100644
--- a/chromium/base/message_loop/message_loop_io_posix_unittest.cc
+++ b/chromium/base/message_loop/message_loop_io_posix_unittest.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/posix/eintr_wrapper.h"
#include "base/run_loop.h"
@@ -134,9 +135,9 @@ TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherOutlivesMessageLoop) {
{
MessageLoopForIO message_loop;
- message_loop.WatchFileDescriptor(write_fd_.get(), true,
- MessagePumpForIO::WATCH_WRITE, &watcher,
- &handler);
+ MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+ write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
+ &handler);
// Don't run the message loop, just destroy it.
}
@@ -153,9 +154,9 @@ TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDoubleStop) {
MessagePumpForIO::FdWatchController watcher(FROM_HERE);
TestHandler handler;
- message_loop.WatchFileDescriptor(write_fd_.get(), true,
- MessagePumpForIO::WATCH_WRITE, &watcher,
- &handler);
+ MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+ write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
+ &handler);
ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
}
@@ -170,9 +171,9 @@ TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDeleteInCallback) {
handler.watcher_to_delete_ =
std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
- message_loop.WatchFileDescriptor(write_fd_.get(), true,
- MessagePumpForIO::WATCH_WRITE,
- handler.watcher_to_delete_.get(), &handler);
+ MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+ write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
+ handler.watcher_to_delete_.get(), &handler);
RunLoop().Run();
}
@@ -183,7 +184,7 @@ TEST_F(MessageLoopForIoPosixTest, WatchReadable) {
TestHandler handler;
// Watch the pipe for readability.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -209,7 +210,7 @@ TEST_F(MessageLoopForIoPosixTest, WatchWritable) {
TestHandler handler;
// Watch the pipe for writability.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
&watcher, &handler));
@@ -232,7 +233,7 @@ TEST_F(MessageLoopForIoPosixTest, RunUntilIdle) {
TestHandler handler;
// Watch the pipe for readability.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -261,7 +262,7 @@ TEST_F(MessageLoopForIoPosixTest, StopFromHandler) {
OnceClosure());
// Create persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -282,7 +283,7 @@ TEST_F(MessageLoopForIoPosixTest, NonPersistentWatcher) {
CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
// Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -303,7 +304,7 @@ TEST_F(MessageLoopForIoPosixTest, PersistentWatcher) {
CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
// Create persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -325,7 +326,7 @@ void StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController* controller,
RunLoop* run_loop) {
controller->StopWatchingFileDescriptor();
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
new_handler));
@@ -345,7 +346,7 @@ TEST_F(MessageLoopForIoPosixTest, StopAndRestartFromHandler) {
OnceClosure());
// Create persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
&watcher, &handler1));
@@ -372,7 +373,7 @@ TEST_F(MessageLoopForIoPosixTest, IoEventThenTimer) {
CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
// Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
@@ -403,7 +404,7 @@ TEST_F(MessageLoopForIoPosixTest, TimerThenIoEvent) {
CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
// Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor(
+ ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
&watcher, &handler));
diff --git a/chromium/base/message_loop/message_loop_task_runner_unittest.cc b/chromium/base/message_loop/message_loop_task_runner_unittest.cc
index f2e71c40e4e..c7e9aa05962 100644
--- a/chromium/base/message_loop/message_loop_task_runner_unittest.cc
+++ b/chromium/base/message_loop/message_loop_task_runner_unittest.cc
@@ -262,8 +262,8 @@ class MessageLoopTaskRunnerThreadingTest : public testing::Test {
}
void Quit() const {
- loop_.task_runner()->PostTask(FROM_HERE,
- MessageLoop::QuitWhenIdleClosure());
+ loop_.task_runner()->PostTask(
+ FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
}
void AssertOnIOThread() const {
diff --git a/chromium/base/message_loop/message_loop_unittest.cc b/chromium/base/message_loop/message_loop_unittest.cc
index e551e420d07..1c0911319dd 100644
--- a/chromium/base/message_loop/message_loop_unittest.cc
+++ b/chromium/base/message_loop/message_loop_unittest.cc
@@ -15,6 +15,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/pending_task.h"
#include "base/posix/eintr_wrapper.h"
@@ -235,7 +236,7 @@ void RecursiveFunc(TaskList* order, int cookie, int depth,
order->RecordStart(RECURSIVE, cookie);
if (depth > 0) {
if (is_reentrant)
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
BindOnce(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
@@ -390,7 +391,7 @@ TEST_P(MessageLoopTest, RunTasksWhileShuttingDownJavaThread) {
#if defined(OS_WIN)
void SubPumpFunc() {
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
@@ -448,7 +449,7 @@ const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
order->RecordStart(MESSAGEBOX, cookie);
if (is_reentrant)
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
order->RecordEnd(MESSAGEBOX, cookie);
}
@@ -639,7 +640,7 @@ TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
}
void TestIOHandler::Init() {
- MessageLoopForIO::current()->RegisterIOHandler(file_.Get(), this);
+ MessageLoopCurrentForIO::Get()->RegisterIOHandler(file_.Get(), this);
DWORD read;
EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
@@ -656,8 +657,8 @@ void TestIOHandler::OnIOCompleted(MessagePumpForIO::IOContext* context,
}
void TestIOHandler::WaitForIO() {
- EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
- EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
+ EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(300, this));
+ EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(400, this));
}
void RunTest_IOHandler() {
@@ -1096,7 +1097,7 @@ void NestingFunc(int* depth) {
ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
BindOnce(&NestingFunc, depth));
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
RunLoop().Run();
}
base::RunLoop::QuitCurrentWhenIdleDeprecated();
@@ -1117,7 +1118,7 @@ TEST_P(MessageLoopTypedTest, Nesting) {
TEST_P(MessageLoopTypedTest, RecursiveDenial1) {
MessageLoop loop(GetMessageLoopType());
- EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
TaskList order;
ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, false));
@@ -1166,7 +1167,7 @@ void OrderedFunc(TaskList* order, int cookie) {
TEST_P(MessageLoopTypedTest, RecursiveDenial3) {
MessageLoop loop(GetMessageLoopType());
- EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
TaskList order;
ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, BindOnce(&RecursiveSlowFunc, &order, 1, 2, false));
@@ -1315,7 +1316,7 @@ namespace {
void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
order->RecordStart(RUNS, cookie);
{
- MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+ MessageLoopCurrent::ScopedNestableTaskAllower allow;
run_loop->Run();
}
order->RecordEnd(RUNS, cookie);
@@ -1659,7 +1660,7 @@ TEST_P(MessageLoopTypedTest, RecursivePosts) {
TEST_P(MessageLoopTypedTest, NestableTasksAllowedAtTopLevel) {
MessageLoop loop(GetMessageLoopType());
- EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
}
// Nestable tasks shouldn't be allowed to run reentrantly by default (regression
@@ -1671,7 +1672,7 @@ TEST_P(MessageLoopTypedTest, NestableTasksDisallowedByDefault) {
FROM_HERE,
BindOnce(
[](RunLoop* run_loop) {
- EXPECT_FALSE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
run_loop->Quit();
},
Unretained(&run_loop)));
@@ -1699,7 +1700,7 @@ TEST_P(MessageLoopTypedTest, NestableTasksProcessedWhenRunLoopAllows) {
// nestable tasks are by default disallowed from this
// layer.
EXPECT_FALSE(
- MessageLoop::current()->NestableTasksAllowed());
+ MessageLoopCurrent::Get()->NestableTasksAllowed());
nested_run_loop->Quit();
},
Unretained(&nested_run_loop)));
@@ -1719,11 +1720,11 @@ TEST_P(MessageLoopTypedTest, NestableTasksAllowedExplicitlyInScope) {
BindOnce(
[](RunLoop* run_loop) {
{
- MessageLoop::ScopedNestableTaskAllower allow_nestable_tasks(
- MessageLoop::current());
- EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
+ MessageLoopCurrent::ScopedNestableTaskAllower
+ allow_nestable_tasks;
+ EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
}
- EXPECT_FALSE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
run_loop->Quit();
},
Unretained(&run_loop)));
@@ -1737,11 +1738,11 @@ TEST_P(MessageLoopTypedTest, NestableTasksAllowedManually) {
FROM_HERE,
BindOnce(
[](RunLoop* run_loop) {
- EXPECT_FALSE(MessageLoop::current()->NestableTasksAllowed());
- MessageLoop::current()->SetNestableTasksAllowed(true);
- EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
- MessageLoop::current()->SetNestableTasksAllowed(false);
- EXPECT_FALSE(MessageLoop::current()->NestableTasksAllowed());
+ EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
+ EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(false);
+ EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
run_loop->Quit();
},
Unretained(&run_loop)));
@@ -1777,13 +1778,14 @@ INSTANTIATE_TEST_CASE_P(
// Run()ning explicitly, via QuitClosure() etc (see https://crbug.com/720078)
TEST_P(MessageLoopTest, WmQuitIsIgnored) {
MessageLoop loop(MessageLoop::TYPE_UI);
- RunLoop run_loop;
+
// Post a WM_QUIT message to the current thread.
::PostQuitMessage(0);
// Post a task to the current thread, with a small delay to make it less
// likely that we process the posted task before looking for WM_* messages.
bool task_was_run = false;
+ RunLoop run_loop;
loop.task_runner()->PostDelayedTask(
FROM_HERE,
BindOnce(
@@ -1799,6 +1801,29 @@ TEST_P(MessageLoopTest, WmQuitIsIgnored) {
EXPECT_TRUE(task_was_run);
}
+TEST_P(MessageLoopTest, WmQuitIsNotIgnoredWithEnableWmQuit) {
+ MessageLoop loop(MessageLoop::TYPE_UI);
+ static_cast<MessageLoopForUI*>(&loop)->EnableWmQuit();
+
+ // Post a WM_QUIT message to the current thread.
+ ::PostQuitMessage(0);
+
+ // Post a task to the current thread, with a small delay to make it less
+ // likely that we process the posted task before looking for WM_* messages.
+ RunLoop run_loop;
+ loop.task_runner()->PostDelayedTask(FROM_HERE,
+ BindOnce(
+ [](OnceClosure closure) {
+ ADD_FAILURE();
+ std::move(closure).Run();
+ },
+ run_loop.QuitClosure()),
+ TestTimeouts::tiny_timeout());
+
+ // Run the loop. It should not result in ADD_FAILURE() getting called.
+ run_loop.Run();
+}
+
TEST_P(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
RunTest_PostDelayedTask_SharedTimer_SubPump();
}
@@ -1910,7 +1935,7 @@ class DestructionObserverProbe :
bool* destruction_observer_called_;
};
-class MLDestructionObserver : public MessageLoop::DestructionObserver {
+class MLDestructionObserver : public MessageLoopCurrent::DestructionObserver {
public:
MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
: task_destroyed_(task_destroyed),
@@ -2030,7 +2055,7 @@ LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
case 2:
// Since we're about to enter a modal loop, tell the message loop that we
// intend to nest tasks.
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
bool did_run = false;
ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EndTest, &did_run, hwnd));
diff --git a/chromium/base/message_loop/message_pump_android.cc b/chromium/base/message_loop/message_pump_android.cc
index 1a11e55325b..8c5bb5727ab 100644
--- a/chromium/base/message_loop/message_pump_android.cc
+++ b/chromium/base/message_loop/message_pump_android.cc
@@ -10,7 +10,6 @@
#include "base/android/scoped_java_ref.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "jni/SystemMessageHandler_jni.h"
diff --git a/chromium/base/message_loop/message_pump_for_ui.h b/chromium/base/message_loop/message_pump_for_ui.h
index 2d3e17513b4..6ee02b094ca 100644
--- a/chromium/base/message_loop/message_pump_for_ui.h
+++ b/chromium/base/message_loop/message_pump_for_ui.h
@@ -15,7 +15,7 @@
#elif defined(OS_ANDROID)
#include "base/message_loop/message_pump_android.h"
#elif defined(OS_MACOSX)
-// No MessagePumpForUI, see below.
+#include "base/message_loop/message_pump.h"
#elif defined(OS_NACL) || defined(OS_AIX)
// No MessagePumpForUI, see below.
#elif defined(USE_GLIB)
@@ -35,8 +35,10 @@ using MessagePumpForUI = MessagePumpForUI;
// Android defines it as-is.
using MessagePumpForUI = MessagePumpForUI;
#elif defined(OS_MACOSX)
-// MessagePumpForUI doesn't exists on Mac, MessagePumpMac::Create defines which
-// Mac specific pump is used.
+// MessagePumpForUI isn't bound to a specific impl on Mac. While each impl can
+// be represented by a plain MessagePump: MessagePumpMac::Create() must be used
+// to instantiate the right impl.
+using MessagePumpForUI = MessagePump;
#elif defined(OS_NACL) || defined(OS_AIX)
// Currently NaCl and AIX don't have a MessagePumpForUI.
// TODO(abarth): Figure out if we need this.
diff --git a/chromium/base/message_loop/message_pump_fuchsia.cc b/chromium/base/message_loop/message_pump_fuchsia.cc
index 6504d177333..b9af6433dd7 100644
--- a/chromium/base/message_loop/message_pump_fuchsia.cc
+++ b/chromium/base/message_loop/message_pump_fuchsia.cc
@@ -4,23 +4,40 @@
#include "base/message_loop/message_pump_fuchsia.h"
+#include <fdio/io.h>
+#include <fdio/private.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include "base/auto_reset.h"
+#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
namespace base {
MessagePumpFuchsia::ZxHandleWatchController::ZxHandleWatchController(
const Location& from_here)
- : created_from_location_(from_here) {}
+ : async_wait_t({}), created_from_location_(from_here) {}
MessagePumpFuchsia::ZxHandleWatchController::~ZxHandleWatchController() {
if (!StopWatchingZxHandle())
NOTREACHED();
}
+bool MessagePumpFuchsia::ZxHandleWatchController::WaitBegin() {
+ DCHECK(!handler);
+ async_wait_t::handler = &HandleSignal;
+
+ zx_status_t status = async_begin_wait(&weak_pump_->async_dispatcher_, this);
+ if (status != ZX_OK) {
+ ZX_DLOG(ERROR, status) << "async_begin_wait() failed";
+ async_wait_t::handler = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
bool MessagePumpFuchsia::ZxHandleWatchController::StopWatchingZxHandle() {
if (was_stopped_) {
DCHECK(!*was_stopped_);
@@ -33,23 +50,64 @@ bool MessagePumpFuchsia::ZxHandleWatchController::StopWatchingZxHandle() {
was_stopped_ = nullptr;
}
- if (!has_begun_)
- return true;
-
- has_begun_ = false;
-
// If the pump is gone then there is nothing to cancel.
if (!weak_pump_)
return true;
- int result = zx_port_cancel(weak_pump_->port_.get(), handle_, wait_key());
- DLOG_IF(ERROR, result != ZX_OK)
- << "zx_port_cancel(handle=" << handle_
- << ") failed: " << zx_status_get_string(result);
+ // |handler| is set when waiting for a signal.
+ if (!handler)
+ return true;
+ async_wait_t::handler = nullptr;
+
+ zx_status_t result = async_cancel_wait(&weak_pump_->async_dispatcher_, this);
+ ZX_DLOG_IF(ERROR, result != ZX_OK, result) << "async_cancel_wait failed";
return result == ZX_OK;
}
+// static
+void MessagePumpFuchsia::ZxHandleWatchController::HandleSignal(
+ async_t* async,
+ async_wait_t* wait,
+ zx_status_t status,
+ const zx_packet_signal_t* signal) {
+ if (status != ZX_OK) {
+ ZX_LOG(WARNING, status) << "async wait failed";
+ return;
+ }
+
+ ZxHandleWatchController* controller =
+ static_cast<ZxHandleWatchController*>(wait);
+ DCHECK_EQ(controller->handler, &HandleSignal);
+ controller->handler = nullptr;
+
+ // |signal| can include other spurious things, in particular, that an fd
+ // is writable, when we only asked to know when it was readable. In that
+ // case, we don't want to call both the CanWrite and CanRead callback,
+ // when the caller asked for only, for example, readable callbacks. So,
+ // mask with the events that we actually wanted to know about.
+ zx_signals_t signals = signal->trigger & signal->observed;
+ DCHECK_NE(0u, signals);
+
+ // In the case of a persistent Watch, the Watch may be stopped and
+ // potentially deleted by the caller within the callback, in which case
+ // |controller| should not be accessed again, and we mustn't continue the
+ // watch. We check for this with a bool on the stack, which the Watch
+ // receives a pointer to.
+ bool was_stopped = false;
+ controller->was_stopped_ = &was_stopped;
+
+ controller->watcher_->OnZxHandleSignalled(wait->object, signals);
+
+ if (was_stopped)
+ return;
+
+ controller->was_stopped_ = nullptr;
+
+ if (controller->persistent_)
+ controller->WaitBegin();
+}
+
void MessagePumpFuchsia::FdWatchController::OnZxHandleSignalled(
zx_handle_t handle,
zx_signals_t signals) {
@@ -79,6 +137,19 @@ MessagePumpFuchsia::FdWatchController::~FdWatchController() {
NOTREACHED();
}
+bool MessagePumpFuchsia::FdWatchController::WaitBegin() {
+ // Refresh the |handle_| and |desired_signals_| from the mxio for the fd.
+ // Some types of fdio map read/write events to different signals depending on
+ // their current state, so we must do this every time we begin to wait.
+ __fdio_wait_begin(io_, desired_events_, &object, &trigger);
+ if (async_wait_t::object == ZX_HANDLE_INVALID) {
+ DLOG(ERROR) << "fdio_wait_begin failed";
+ return false;
+ }
+
+ return MessagePumpFuchsia::ZxHandleWatchController::WaitBegin();
+}
+
bool MessagePumpFuchsia::FdWatchController::StopWatchingFileDescriptor() {
bool success = StopWatchingZxHandle();
if (io_) {
@@ -88,11 +159,9 @@ bool MessagePumpFuchsia::FdWatchController::StopWatchingFileDescriptor() {
return success;
}
-MessagePumpFuchsia::MessagePumpFuchsia() : weak_factory_(this) {
- CHECK_EQ(ZX_OK, zx_port_create(0, port_.receive()));
-}
+MessagePumpFuchsia::MessagePumpFuchsia() : weak_factory_(this) {}
-MessagePumpFuchsia::~MessagePumpFuchsia() {}
+MessagePumpFuchsia::~MessagePumpFuchsia() = default;
bool MessagePumpFuchsia::WatchFileDescriptor(int fd,
bool persistent,
@@ -138,19 +207,6 @@ bool MessagePumpFuchsia::WatchFileDescriptor(int fd,
controller);
}
-bool MessagePumpFuchsia::FdWatchController::WaitBegin() {
- // Refresh the |handle_| and |desired_signals_| from the mxio for the fd.
- // Some types of mxio map read/write events to different signals depending on
- // their current state, so we must do this every time we begin to wait.
- __fdio_wait_begin(io_, desired_events_, &handle_, &desired_signals_);
- if (handle_ == ZX_HANDLE_INVALID) {
- DLOG(ERROR) << "fdio_wait_begin failed";
- return false;
- }
-
- return MessagePumpFuchsia::ZxHandleWatchController::WaitBegin();
-}
-
bool MessagePumpFuchsia::WatchZxHandle(zx_handle_t handle,
bool persistent,
zx_signals_t signals,
@@ -160,15 +216,15 @@ bool MessagePumpFuchsia::WatchZxHandle(zx_handle_t handle,
DCHECK(controller);
DCHECK(delegate);
DCHECK(handle == ZX_HANDLE_INVALID ||
- controller->handle_ == ZX_HANDLE_INVALID ||
- handle == controller->handle_);
+ controller->async_wait_t::object == ZX_HANDLE_INVALID ||
+ handle == controller->async_wait_t::object);
if (!controller->StopWatchingZxHandle())
NOTREACHED();
- controller->handle_ = handle;
+ controller->async_wait_t::object = handle;
controller->persistent_ = persistent;
- controller->desired_signals_ = signals;
+ controller->async_wait_t::trigger = signals;
controller->watcher_ = delegate;
controller->weak_pump_ = weak_factory_.GetWeakPtr();
@@ -176,85 +232,22 @@ bool MessagePumpFuchsia::WatchZxHandle(zx_handle_t handle,
return controller->WaitBegin();
}
-bool MessagePumpFuchsia::ZxHandleWatchController::WaitBegin() {
- DCHECK(!has_begun_);
-
- zx_status_t status =
- zx_object_wait_async(handle_, weak_pump_->port_.get(), wait_key(),
- desired_signals_, ZX_WAIT_ASYNC_ONCE);
- if (status != ZX_OK) {
- DLOG(ERROR) << "zx_object_wait_async failed: "
- << zx_status_get_string(status)
- << " (port=" << weak_pump_->port_.get() << ")";
- return false;
- }
-
- has_begun_ = true;
-
- return true;
-}
-
-uint32_t MessagePumpFuchsia::ZxHandleWatchController::WaitEnd(
- zx_signals_t signals) {
- DCHECK(has_begun_);
-
- has_begun_ = false;
-
- // |signals| can include other spurious things, in particular, that an fd
- // is writable, when we only asked to know when it was readable. In that
- // case, we don't want to call both the CanWrite and CanRead callback,
- // when the caller asked for only, for example, readable callbacks. So,
- // mask with the events that we actually wanted to know about.
- signals &= desired_signals_;
- return signals;
-}
-
bool MessagePumpFuchsia::HandleEvents(zx_time_t deadline) {
- zx_port_packet_t packet;
- const zx_status_t wait_status =
- zx_port_wait(port_.get(), deadline, &packet, 0);
-
- if (wait_status == ZX_ERR_TIMED_OUT)
- return false;
-
- if (wait_status != ZX_OK) {
- NOTREACHED() << "unexpected wait status: "
- << zx_status_get_string(wait_status);
- return false;
- }
+ zx_status_t status = async_dispatcher_.DispatchOrWaitUntil(deadline);
+ switch (status) {
+ // Return true if some tasks or events were dispatched or if the dispatcher
+ // was stopped by ScheduleWork().
+ case ZX_OK:
+ case ZX_ERR_CANCELED:
+ return true;
+
+ case ZX_ERR_TIMED_OUT:
+ return false;
- if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE) {
- // A watched fd caused the wakeup via zx_object_wait_async().
- DCHECK_EQ(ZX_OK, packet.status);
- ZxHandleWatchController* controller =
- reinterpret_cast<ZxHandleWatchController*>(
- static_cast<uintptr_t>(packet.key));
-
- DCHECK_NE(0u, packet.signal.trigger & packet.signal.observed);
-
- zx_signals_t signals = controller->WaitEnd(packet.signal.observed);
-
- // In the case of a persistent Watch, the Watch may be stopped and
- // potentially deleted by the caller within the callback, in which case
- // |controller| should not be accessed again, and we mustn't continue the
- // watch. We check for this with a bool on the stack, which the Watch
- // receives a pointer to.
- bool controller_was_stopped = false;
- controller->was_stopped_ = &controller_was_stopped;
-
- controller->watcher_->OnZxHandleSignalled(controller->handle_, signals);
-
- if (!controller_was_stopped) {
- controller->was_stopped_ = nullptr;
- if (controller->persistent_)
- controller->WaitBegin();
- }
- } else {
- // Wakeup caused by ScheduleWork().
- DCHECK_EQ(ZX_PKT_TYPE_USER, packet.type);
+ default:
+ ZX_DLOG(DCHECK, status) << "unexpected wait status";
+ return false;
}
-
- return true;
}
void MessagePumpFuchsia::Run(Delegate* delegate) {
@@ -295,13 +288,9 @@ void MessagePumpFuchsia::Quit() {
}
void MessagePumpFuchsia::ScheduleWork() {
- // Since this can be called on any thread, we need to ensure that our Run loop
- // wakes up.
- zx_port_packet_t packet = {};
- packet.type = ZX_PKT_TYPE_USER;
- zx_status_t status = zx_port_queue(port_.get(), &packet, 0);
- DLOG_IF(ERROR, status != ZX_OK)
- << "zx_port_queue failed: " << status << " (port=" << port_.get() << ")";
+ // Stop AsyncDispatcher to let MessagePumpFuchsia::Run() handle message loop
+ // tasks.
+ async_dispatcher_.Stop();
}
void MessagePumpFuchsia::ScheduleDelayedWork(
diff --git a/chromium/base/message_loop/message_pump_fuchsia.h b/chromium/base/message_loop/message_pump_fuchsia.h
index dbcd7d4dc38..514e23f79bf 100644
--- a/chromium/base/message_loop/message_pump_fuchsia.h
+++ b/chromium/base/message_loop/message_pump_fuchsia.h
@@ -5,17 +5,17 @@
#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_
#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_
+#include <lib/async/wait.h>
+
#include "base/base_export.h"
-#include "base/fuchsia/scoped_zx_handle.h"
+#include "base/fuchsia/async_dispatcher.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_pump.h"
#include "base/message_loop/watchable_io_message_pump_posix.h"
-#include <fdio/io.h>
-#include <fdio/private.h>
-#include <zircon/syscalls/port.h>
+typedef struct fdio fdio_t;
namespace base {
@@ -33,7 +33,7 @@ class BASE_EXPORT MessagePumpFuchsia : public MessagePump,
};
// Manages an active watch on an zx_handle_t.
- class ZxHandleWatchController {
+ class ZxHandleWatchController : public async_wait_t {
public:
explicit ZxHandleWatchController(const Location& from_here);
// Deleting the Controller implicitly calls StopWatchingZxHandle.
@@ -46,6 +46,17 @@ class BASE_EXPORT MessagePumpFuchsia : public MessagePump,
const Location& created_from_location() { return created_from_location_; }
protected:
+ friend class MessagePumpFuchsia;
+
+ virtual bool WaitBegin();
+
+ static void HandleSignal(async_t* async,
+ async_wait_t* wait,
+ zx_status_t status,
+ const zx_packet_signal_t* signal);
+
+ const Location created_from_location_;
+
// This bool is used by the pump when invoking the ZxHandleWatcher callback,
// and by the FdHandleWatchController when invoking read & write callbacks,
// to cope with the possibility of the caller deleting the *Watcher within
@@ -54,28 +65,8 @@ class BASE_EXPORT MessagePumpFuchsia : public MessagePump,
// to check the value on the stack to short-cut any post-callback work.
bool* was_stopped_ = nullptr;
- protected:
- friend class MessagePumpFuchsia;
-
- // Start watching the handle.
- virtual bool WaitBegin();
-
- // Called by MessagePumpFuchsia when the handle is signalled. Accepts the
- // set of signals that fired, and returns the intersection with those the
- // caller is interested in.
- zx_signals_t WaitEnd(zx_signals_t observed);
-
- // Returns the key to use to uniquely identify this object's wait operation.
- uint64_t wait_key() const {
- return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this));
- }
-
- const Location created_from_location_;
-
// Set directly from the inputs to WatchFileDescriptor.
ZxHandleWatcher* watcher_ = nullptr;
- zx_handle_t handle_ = ZX_HANDLE_INVALID;
- zx_signals_t desired_signals_ = 0;
// Used to safely access resources owned by the associated message pump.
WeakPtr<MessagePumpFuchsia> weak_pump_;
@@ -84,10 +75,6 @@ class BASE_EXPORT MessagePumpFuchsia : public MessagePump,
// after triggering.
bool persistent_ = false;
- // Used to determine whether an asynchronous wait operation is active on
- // this controller.
- bool has_begun_ = false;
-
DISALLOW_COPY_AND_ASSIGN(ZxHandleWatchController);
};
@@ -148,14 +135,14 @@ class BASE_EXPORT MessagePumpFuchsia : public MessagePump,
void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
private:
- // Handles IO events from the |port_|. Returns true if any events were
- // received.
+ // Handles IO events by running |async_dispatcher_|. Returns true if any
+ // events were received or if ScheduleWork() was called.
bool HandleEvents(zx_time_t deadline);
// This flag is set to false when Run should return.
bool keep_running_ = true;
- ScopedZxHandle port_;
+ AsyncDispatcher async_dispatcher_;
// The time at which we should call DoDelayedWork.
TimeTicks delayed_work_time_;
diff --git a/chromium/base/message_loop/message_pump_glib_unittest.cc b/chromium/base/message_loop/message_pump_glib_unittest.cc
index 451c6f5caa2..70be2a4f74c 100644
--- a/chromium/base/message_loop/message_pump_glib_unittest.cc
+++ b/chromium/base/message_loop/message_pump_glib_unittest.cc
@@ -16,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
@@ -190,7 +191,7 @@ TEST_F(MessagePumpGLibTest, TestQuit) {
injector()->Reset();
// Quit from an event
- injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+ injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
RunLoop().Run();
EXPECT_EQ(1, injector()->processed_events());
}
@@ -210,7 +211,7 @@ TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) {
BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task));
injector()->AddEventAsTask(0, std::move(posted_task));
injector()->AddEventAsTask(0, DoNothing());
- injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+ injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
RunLoop().Run();
EXPECT_EQ(4, injector()->processed_events());
@@ -221,7 +222,7 @@ TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) {
BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task));
injector()->AddEventAsTask(0, std::move(posted_task));
injector()->AddEventAsTask(10, DoNothing());
- injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+ injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
RunLoop().Run();
EXPECT_EQ(4, injector()->processed_events());
}
@@ -238,7 +239,7 @@ TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) {
// quit.
loop()->task_runner()->PostTask(
FROM_HERE, BindOnce(&EventInjector::AddEvent, Unretained(injector()), 0,
- MessageLoop::QuitWhenIdleClosure()));
+ RunLoop::QuitCurrentWhenIdleClosureDeprecated()));
RunLoop().Run();
ASSERT_EQ(10, task_count);
EXPECT_EQ(1, injector()->processed_events());
@@ -258,7 +259,7 @@ TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) {
loop()->task_runner()->PostDelayedTask(
FROM_HERE,
BindOnce(&EventInjector::AddEvent, Unretained(injector()), 10,
- MessageLoop::QuitWhenIdleClosure()),
+ RunLoop::QuitCurrentWhenIdleClosureDeprecated()),
TimeDelta::FromMilliseconds(150));
RunLoop().Run();
ASSERT_EQ(10, task_count);
@@ -281,7 +282,7 @@ TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) {
injector()->AddEventAsTask(10, std::move(posted_task));
// And then quit (relies on the condition tested by TestEventTaskInterleave).
- injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure());
+ injector()->AddEvent(10, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
RunLoop().Run();
EXPECT_EQ(12, injector()->processed_events());
@@ -373,7 +374,7 @@ void AddEventsAndDrainGLib(EventInjector* injector) {
injector->AddDummyEvent(0);
injector->AddDummyEvent(0);
// Then add an event that will quit the main loop.
- injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
+ injector->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
// Post a couple of dummy tasks
ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
@@ -433,7 +434,7 @@ class GLibLoopRunner : public RefCounted<GLibLoopRunner> {
void TestGLibLoopInternal(EventInjector* injector) {
// Allow tasks to be processed from 'native' event loops.
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
int task_count = 0;
@@ -466,7 +467,7 @@ void TestGLibLoopInternal(EventInjector* injector) {
void TestGtkLoopInternal(EventInjector* injector) {
// Allow tasks to be processed from 'native' event loops.
- MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
int task_count = 0;
diff --git a/chromium/base/message_loop/message_pump_io_ios_unittest.cc b/chromium/base/message_loop/message_pump_io_ios_unittest.cc
index dc78309590f..4d15d44db32 100644
--- a/chromium/base/message_loop/message_pump_io_ios_unittest.cc
+++ b/chromium/base/message_loop/message_pump_io_ios_unittest.cc
@@ -7,7 +7,6 @@
#include <unistd.h>
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/posix/eintr_wrapper.h"
#include "base/test/gtest_util.h"
#include "base/threading/thread.h"
@@ -17,15 +16,10 @@ namespace base {
class MessagePumpIOSForIOTest : public testing::Test {
protected:
- MessagePumpIOSForIOTest()
- : ui_loop_(MessageLoop::TYPE_UI),
- io_thread_("MessagePumpIOSForIOTestIOThread") {}
- ~MessagePumpIOSForIOTest() override {}
+ MessagePumpIOSForIOTest() = default;
+ ~MessagePumpIOSForIOTest() override = default;
void SetUp() override {
- Thread::Options options(MessageLoop::TYPE_IO, 0);
- ASSERT_TRUE(io_thread_.StartWithOptions(options));
- ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
int ret = pipe(pipefds_);
ASSERT_EQ(0, ret);
ret = pipe(alternate_pipefds_);
@@ -39,11 +33,6 @@ class MessagePumpIOSForIOTest : public testing::Test {
PLOG(ERROR) << "close";
}
- MessageLoop* ui_loop() { return &ui_loop_; }
- MessageLoopForIO* io_loop() const {
- return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
- }
-
void HandleFdIOEvent(MessagePumpForIO::FdWatchController* watcher) {
MessagePumpIOSForIO::HandleFdIOEvent(watcher->fdref_.get(),
kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack,
@@ -54,9 +43,6 @@ class MessagePumpIOSForIOTest : public testing::Test {
int alternate_pipefds_[2];
private:
- MessageLoop ui_loop_;
- Thread io_thread_;
-
DISALLOW_COPY_AND_ASSIGN(MessagePumpIOSForIOTest);
};
@@ -73,16 +59,6 @@ class StupidWatcher : public MessagePumpIOSForIO::FdWatcher {
void OnFileCanWriteWithoutBlocking(int fd) override {}
};
-// Test to make sure that we catch calling WatchFileDescriptor off of the wrong
-// thread.
-TEST_F(MessagePumpIOSForIOTest, TestWatchingFromBadThread) {
- MessagePumpIOSForIO::FdWatchController watcher(FROM_HERE);
- StupidWatcher delegate;
-
- ASSERT_DCHECK_DEATH(io_loop()->WatchFileDescriptor(
- STDOUT_FILENO, false, MessagePumpForIO::WATCH_READ, &watcher, &delegate));
-}
-
class BaseWatcher : public MessagePumpIOSForIO::FdWatcher {
public:
BaseWatcher(MessagePumpIOSForIO::FdWatchController* controller)
diff --git a/chromium/base/message_loop/message_pump_libevent_unittest.cc b/chromium/base/message_loop/message_pump_libevent_unittest.cc
index 0444e35ace2..55eb0b4d728 100644
--- a/chromium/base/message_loop/message_pump_libevent_unittest.cc
+++ b/chromium/base/message_loop/message_pump_libevent_unittest.cc
@@ -55,8 +55,8 @@ class MessagePumpLibeventTest : public testing::Test {
ASSERT_TRUE(io_thread_.WaitUntilThreadStarted());
}
- MessageLoopForIO* io_loop() const {
- return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
+ scoped_refptr<SingleThreadTaskRunner> io_runner() const {
+ return io_thread_.task_runner();
}
void OnLibeventNotification(
@@ -85,20 +85,6 @@ class StupidWatcher : public MessagePumpLibevent::FdWatcher {
void OnFileCanWriteWithoutBlocking(int fd) override {}
};
-// Test to make sure that we catch calling WatchFileDescriptor off of the
-// wrong thread.
-TEST_F(MessagePumpLibeventTest, TestWatchingFromBadThread) {
- MessagePumpLibevent::FdWatchController watcher(FROM_HERE);
- StupidWatcher delegate;
-
- // Ensure that |io_thread_| has started, otherwise we're racing against
- // creation of the thread's MessagePump.
- WaitUntilIoThreadStarted();
-
- ASSERT_DCHECK_DEATH(io_loop()->WatchFileDescriptor(
- STDOUT_FILENO, false, MessagePumpForIO::WATCH_READ, &watcher, &delegate));
-}
-
TEST_F(MessagePumpLibeventTest, QuitOutsideOfRun) {
std::unique_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
ASSERT_DCHECK_DEATH(pump->Quit());
@@ -255,10 +241,10 @@ TEST_F(MessagePumpLibeventTest, QuitWatcher) {
const char buf = 0;
WaitableEventWatcher::EventCallback write_fd_task =
BindOnce(&WriteFDWrapper, pipefds_[1], &buf, 1);
- io_loop()->task_runner()->PostTask(
+ io_runner()->PostTask(
FROM_HERE, BindOnce(IgnoreResult(&WaitableEventWatcher::StartWatching),
Unretained(watcher.get()), &event,
- std::move(write_fd_task), io_loop()->task_runner()));
+ std::move(write_fd_task), io_runner()));
// Queue |event| to signal on |loop|.
loop.task_runner()->PostTask(
@@ -268,9 +254,8 @@ TEST_F(MessagePumpLibeventTest, QuitWatcher) {
run_loop.Run();
// StartWatching can move |watcher| to IO thread. Release on IO thread.
- io_loop()->task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEventWatcher::StopWatching, Owned(watcher.release())));
+ io_runner()->PostTask(FROM_HERE, BindOnce(&WaitableEventWatcher::StopWatching,
+ Owned(watcher.release())));
}
} // namespace
diff --git a/chromium/base/message_loop/message_pump_mac.mm b/chromium/base/message_loop/message_pump_mac.mm
index eed9247079e..fb252017999 100644
--- a/chromium/base/message_loop/message_pump_mac.mm
+++ b/chromium/base/message_loop/message_pump_mac.mm
@@ -25,41 +25,12 @@
namespace base {
-// kMessageLoopExclusiveRunLoopMode must be defined before kAllModes to generate
-// a sane static initialization order.
const CFStringRef kMessageLoopExclusiveRunLoopMode =
CFSTR("kMessageLoopExclusiveRunLoopMode");
namespace {
-// kCFRunLoopCommonModes is const but not constexpr; hence kAllModes is
-// initialized at run-time. This initialization being trivial, constant, and
-// without side-effects: this is fine.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wglobal-constructors"
-
-// AppKit RunLoop modes observed to potentially run tasks posted to Chrome's
-// main thread task runner. Some are internal to AppKit but must be observed to
-// keep Chrome's UI responsive. Others that may be interesting, but are not
-// watched:
-// - com.apple.hitoolbox.windows.transitionmode
-// - com.apple.hitoolbox.windows.flushmode
-const CFStringRef kAllModes[] = {
- kCFRunLoopCommonModes,
-
- // Mode that only sees Chrome work sources.
- kMessageLoopExclusiveRunLoopMode,
-
- // Process work when NSMenus are fading out.
- CFSTR("com.apple.hitoolbox.windows.windowfadingmode"),
-
- // Process work when AppKit is highlighting an item on the main menubar.
- CFSTR("NSUnhighlightMenuRunLoopMode"),
-};
-
-#pragma clang diagnostic pop // -Wglobal-constructors
-
-// Mask that determines which modes in |kAllModes| to use.
+// Mask that determines which modes to use.
enum { kCommonModeMask = 0x1, kAllModesMask = 0xf };
// Modes to use for MessagePumpNSApplication that are considered "safe".
@@ -85,9 +56,7 @@ MessagePumpNSApplication* g_app_pump;
typedef struct __CFRuntimeBase {
uintptr_t _cfisa;
uint8_t _cfinfo[4];
-#if __LP64__
uint32_t _rc;
-#endif
} CFRuntimeBase;
#if defined(__BIG_ENDIAN__)
@@ -167,7 +136,33 @@ class MessagePumpCFRunLoopBase::ScopedModeEnabler {
CFRunLoopRemoveTimer(loop, owner_->delayed_work_timer_, mode());
}
- const CFStringRef& mode() const { return kAllModes[mode_index_]; }
+ // This function knows about the AppKit RunLoop modes observed to potentially
+ // run tasks posted to Chrome's main thread task runner. Some are internal to
+ // AppKit but must be observed to keep Chrome's UI responsive. Others that may
+ // be interesting, but are not watched:
+ // - com.apple.hitoolbox.windows.transitionmode
+ // - com.apple.hitoolbox.windows.flushmode
+ const CFStringRef& mode() const {
+ static const CFStringRef modes[] = {
+ // The standard Core Foundation "common modes" constant. Must always be
+ // first in this list to match the value of kCommonModeMask.
+ kCFRunLoopCommonModes,
+
+ // Mode that only sees Chrome work sources.
+ kMessageLoopExclusiveRunLoopMode,
+
+ // Process work when NSMenus are fading out.
+ CFSTR("com.apple.hitoolbox.windows.windowfadingmode"),
+
+ // Process work when AppKit is highlighting an item on the main menubar.
+ CFSTR("NSUnhighlightMenuRunLoopMode"),
+ };
+ static_assert(arraysize(modes) == kNumModes, "mode size mismatch");
+ static_assert((1 << kNumModes) - 1 == kAllModesMask,
+ "kAllModesMask not large enough");
+
+ return modes[mode_index_];
+ }
private:
MessagePumpCFRunLoopBase* const owner_; // Weak. Owns this.
@@ -331,9 +326,7 @@ AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
}
void MessagePumpCFRunLoopBase::SetModeMask(int mode_mask) {
- static_assert(arraysize(enabled_modes_) == arraysize(kAllModes),
- "mode size mismatch");
- for (size_t i = 0; i < arraysize(kAllModes); ++i) {
+ for (size_t i = 0; i < kNumModes; ++i) {
bool enable = mode_mask & (0x1 << i);
if (enable == !enabled_modes_[i]) {
enabled_modes_[i] =
@@ -344,7 +337,7 @@ void MessagePumpCFRunLoopBase::SetModeMask(int mode_mask) {
int MessagePumpCFRunLoopBase::GetModeMask() const {
int mask = 0;
- for (size_t i = 0; i < arraysize(enabled_modes_); ++i)
+ for (size_t i = 0; i < kNumModes; ++i)
mask |= enabled_modes_[i] ? (0x1 << i) : 0;
return mask;
}
diff --git a/chromium/base/message_loop/message_pump_mac_unittest.mm b/chromium/base/message_loop/message_pump_mac_unittest.mm
index 480b311fa38..6b63aa14f5d 100644
--- a/chromium/base/message_loop/message_pump_mac_unittest.mm
+++ b/chromium/base/message_loop/message_pump_mac_unittest.mm
@@ -8,6 +8,7 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -131,7 +132,7 @@ namespace {
// the counter incremented after emptying that run loop mode.
void IncrementInModeAndExpect(CFRunLoopMode mode, int result) {
// Since this task is "ours" rather than a system task, allow nesting.
- MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+ MessageLoopCurrent::ScopedNestableTaskAllower allow;
int counter = 0;
auto increment = BindRepeating([](int* i) { ++*i; }, &counter);
ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, increment);
diff --git a/chromium/base/message_loop/message_pump_perftest.cc b/chromium/base/message_loop/message_pump_perftest.cc
index cadd58e64f3..76f18cb467e 100644
--- a/chromium/base/message_loop/message_pump_perftest.cc
+++ b/chromium/base/message_loop/message_pump_perftest.cc
@@ -9,6 +9,7 @@
#include "base/bind_helpers.h"
#include "base/format_macros.h"
#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/condition_variable.h"
diff --git a/chromium/base/message_loop/message_pump_win.cc b/chromium/base/message_loop/message_pump_win.cc
index ca257370fb5..68bb4c08465 100644
--- a/chromium/base/message_loop/message_pump_win.cc
+++ b/chromium/base/message_loop/message_pump_win.cc
@@ -11,7 +11,6 @@
#include "base/debug/alias.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
@@ -128,6 +127,10 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
RescheduleTimer();
}
+void MessagePumpForUI::EnableWmQuit() {
+ enable_wm_quit_ = true;
+}
+
//-----------------------------------------------------------------------------
// MessagePumpForUI private:
@@ -351,9 +354,17 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) {
TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper",
"message", msg.message);
if (WM_QUIT == msg.message) {
+ if (enable_wm_quit_) {
+ // Repost the QUIT message so that it will be retrieved by the primary
+ // GetMessage() loop.
+ state_->should_quit = true;
+ PostQuitMessage(static_cast<int>(msg.wParam));
+ return false;
+ }
+
// WM_QUIT is the standard way to exit a GetMessage() loop. Our MessageLoop
// has its own quit mechanism, so WM_QUIT is unexpected and should be
- // ignored.
+ // ignored when |enable_wm_quit_| is set to false.
UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem",
RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX);
return true;
diff --git a/chromium/base/message_loop/message_pump_win.h b/chromium/base/message_loop/message_pump_win.h
index f8a8557014b..c1f96bd1e24 100644
--- a/chromium/base/message_loop/message_pump_win.h
+++ b/chromium/base/message_loop/message_pump_win.h
@@ -124,6 +124,9 @@ class BASE_EXPORT MessagePumpForUI : public MessagePumpWin {
void ScheduleWork() override;
void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
+ // Make the MessagePumpForUI respond to WM_QUIT messages.
+ void EnableWmQuit();
+
private:
bool MessageCallback(
UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result);
@@ -137,6 +140,10 @@ class BASE_EXPORT MessagePumpForUI : public MessagePumpWin {
bool ProcessPumpReplacementMessage();
base::win::MessageWindow message_window_;
+
+ // Whether MessagePumpForUI responds to WM_QUIT messages or not.
+ // TODO(thestig): Remove when the Cloud Print Service goes away.
+ bool enable_wm_quit_ = false;
};
//-----------------------------------------------------------------------------