base: Remove MessageLoopProxy
BUG=465354
Review URL: https://codereview.chromium.org/1180153002
Cr-Commit-Position: refs/heads/master@{#335277}
CrOS-Libchrome-Original-Commit: b1f02993d46e10a58aeda7acc299350381046fa6
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 4222c77..0eb24cf 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -170,7 +170,7 @@
// Tell the incoming queue that we are dying.
incoming_task_queue_->WillDestroyCurrentMessageLoop();
incoming_task_queue_ = NULL;
- message_loop_proxy_ = NULL;
+ task_runner_ = NULL;
// OK, now make it so that no one can find us.
lazy_tls_ptr.Pointer()->Set(NULL);
@@ -257,27 +257,27 @@
void MessageLoop::PostTask(
const tracked_objects::Location& from_here,
const Closure& task) {
- message_loop_proxy_->PostTask(from_here, task);
+ task_runner_->PostTask(from_here, task);
}
void MessageLoop::PostDelayedTask(
const tracked_objects::Location& from_here,
const Closure& task,
TimeDelta delay) {
- message_loop_proxy_->PostDelayedTask(from_here, task, delay);
+ task_runner_->PostDelayedTask(from_here, task, delay);
}
void MessageLoop::PostNonNestableTask(
const tracked_objects::Location& from_here,
const Closure& task) {
- message_loop_proxy_->PostNonNestableTask(from_here, task);
+ task_runner_->PostNonNestableTask(from_here, task);
}
void MessageLoop::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const Closure& task,
TimeDelta delay) {
- message_loop_proxy_->PostNonNestableDelayedTask(from_here, task, delay);
+ task_runner_->PostNonNestableDelayedTask(from_here, task, delay);
}
void MessageLoop::Run() {
@@ -386,8 +386,7 @@
message_histogram_(NULL),
run_loop_(NULL),
incoming_task_queue_(new internal::IncomingTaskQueue(this)),
- message_loop_proxy_(
- new internal::MessageLoopProxyImpl(incoming_task_queue_)) {
+ task_runner_(new internal::MessageLoopTaskRunner(incoming_task_queue_)) {
// If type is TYPE_CUSTOM non-null pump_factory must be given.
DCHECK_EQ(type_ == TYPE_CUSTOM, !pump_factory_.is_null());
}
@@ -403,9 +402,8 @@
lazy_tls_ptr.Pointer()->Set(this);
incoming_task_queue_->StartScheduling();
- message_loop_proxy_->BindToCurrentThread();
- thread_task_runner_handle_.reset(
- new ThreadTaskRunnerHandle(message_loop_proxy_));
+ task_runner_->BindToCurrentThread();
+ thread_task_runner_handle_.reset(new ThreadTaskRunnerHandle(task_runner_));
}
void MessageLoop::RunHandler() {
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index f2f89d0..9c635ee 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -16,8 +16,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/incoming_task_queue.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/message_loop/message_loop_proxy_impl.h"
+#include "base/message_loop/message_loop_task_runner.h"
#include "base/message_loop/message_pump.h"
#include "base/message_loop/timer_slack.h"
#include "base/observer_list.h"
@@ -296,19 +295,10 @@
}
const std::string& thread_name() const { return thread_name_; }
- // Gets the message loop proxy associated with this message loop.
- //
- // NOTE: Deprecated; prefer task_runner() and the TaskRunner interfaces
- scoped_refptr<MessageLoopProxy> message_loop_proxy() {
- return message_loop_proxy_;
- }
-
// Gets the TaskRunner associated with this message loop.
// TODO(skyostil): Change this to return a const reference to a refptr
// once the internal type matches what is being returned (crbug.com/465354).
- scoped_refptr<SingleThreadTaskRunner> task_runner() {
- return message_loop_proxy_;
- }
+ scoped_refptr<SingleThreadTaskRunner> task_runner() { return task_runner_; }
// Enables or disables the recursive task processing. This happens in the case
// of recursive message loops. Some unwanted message loop may occurs when
@@ -531,8 +521,8 @@
scoped_refptr<internal::IncomingTaskQueue> incoming_task_queue_;
- // The message loop proxy associated with this message loop.
- scoped_refptr<internal::MessageLoopProxyImpl> message_loop_proxy_;
+ // The task runner associated with this message loop.
+ scoped_refptr<internal::MessageLoopTaskRunner> task_runner_;
scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
template <class T, class R> friend class base::subtle::DeleteHelperInternal;
diff --git a/base/message_loop/message_loop_proxy.cc b/base/message_loop/message_loop_proxy.cc
deleted file mode 100644
index e5f0142..0000000
--- a/base/message_loop/message_loop_proxy.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2012 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_proxy.h"
-
-#include "base/bind.h"
-
-namespace base {
-
-MessageLoopProxy::MessageLoopProxy() {
-}
-
-MessageLoopProxy::~MessageLoopProxy() {
-}
-
-} // namespace base
diff --git a/base/message_loop/message_loop_proxy.h b/base/message_loop/message_loop_proxy.h
deleted file mode 100644
index d5ecc04..0000000
--- a/base/message_loop/message_loop_proxy.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 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_PROXY_H_
-#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_H_
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-
-// MessageLoopProxy is deprecated. Code should prefer to depend on TaskRunner
-// (or the various specializations) for passing task runners around, and should
-// use ThreadTaskRunnerHandle::Get() to get the thread's associated task runner.
-//
-// See http://crbug.com/391045 for more details.
-// Example for these changes:
-//
-// base::MessageLoopProxy::current() -> base::ThreadTaskRunnerHandle::Get()
-// scoped_refptr<base::MessageLoopProxy> ->
-// scoped_refptr<base::SingleThreadTaskRunner>
-// base::MessageLoopProxy -> base::SingleThreadTaskRunner
-
-namespace base {
-
-// This class provides a thread-safe refcounted interface to the Post* methods
-// of a message loop. This class can outlive the target message loop.
-// MessageLoopProxy objects are constructed automatically for all MessageLoops.
-// So, to access them, you can use any of the following:
-// Thread::message_loop_proxy()
-// MessageLoop::current()->message_loop_proxy()
-// MessageLoopProxy::current()
-//
-// TODO(akalin): Now that we have the *TaskRunner interfaces, we can
-// merge this with MessageLoopProxyImpl.
-class BASE_EXPORT MessageLoopProxy : public SingleThreadTaskRunner {
- public:
- // Gets the MessageLoopProxy for the current message loop, creating one if
- // needed.
- static scoped_refptr<MessageLoopProxy> current();
-
- protected:
- MessageLoopProxy();
- ~MessageLoopProxy() override;
-};
-
-} // namespace base
-
-#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_H_
diff --git a/base/message_loop/message_loop_proxy_impl_unittest.cc b/base/message_loop/message_loop_proxy_impl_unittest.cc
deleted file mode 100644
index fa25371..0000000
--- a/base/message_loop/message_loop_proxy_impl_unittest.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2012 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_proxy_impl.h"
-
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-
-class MessageLoopProxyImplTest : public testing::Test {
- public:
- void Release() const {
- AssertOnIOThread();
- Quit();
- }
-
- void Quit() const {
- loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure());
- }
-
- void AssertOnIOThread() const {
- ASSERT_TRUE(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
- ASSERT_EQ(io_thread_->message_loop_proxy(),
- MessageLoopProxy::current());
- }
-
- void AssertOnFileThread() const {
- ASSERT_TRUE(file_thread_->message_loop_proxy()->BelongsToCurrentThread());
- ASSERT_EQ(file_thread_->message_loop_proxy(),
- MessageLoopProxy::current());
- }
-
- protected:
- void SetUp() override {
- io_thread_.reset(new Thread("MessageLoopProxyImplTest_IO"));
- file_thread_.reset(new Thread("MessageLoopProxyImplTest_File"));
- io_thread_->Start();
- file_thread_->Start();
- }
-
- void TearDown() override {
- io_thread_->Stop();
- file_thread_->Stop();
- }
-
- static void BasicFunction(MessageLoopProxyImplTest* test) {
- test->AssertOnFileThread();
- test->Quit();
- }
-
- static void AssertNotRun() {
- FAIL() << "Callback Should not get executed.";
- }
-
- class DeletedOnFile {
- public:
- explicit DeletedOnFile(MessageLoopProxyImplTest* test) : test_(test) {}
-
- ~DeletedOnFile() {
- test_->AssertOnFileThread();
- test_->Quit();
- }
-
- private:
- MessageLoopProxyImplTest* test_;
- };
-
- scoped_ptr<Thread> io_thread_;
- scoped_ptr<Thread> file_thread_;
-
- private:
- mutable MessageLoop loop_;
-};
-
-TEST_F(MessageLoopProxyImplTest, Release) {
- EXPECT_TRUE(io_thread_->message_loop_proxy()->ReleaseSoon(FROM_HERE, this));
- MessageLoop::current()->Run();
-}
-
-TEST_F(MessageLoopProxyImplTest, Delete) {
- DeletedOnFile* deleted_on_file = new DeletedOnFile(this);
- EXPECT_TRUE(file_thread_->message_loop_proxy()->DeleteSoon(
- FROM_HERE, deleted_on_file));
- MessageLoop::current()->Run();
-}
-
-TEST_F(MessageLoopProxyImplTest, PostTask) {
- EXPECT_TRUE(file_thread_->message_loop_proxy()->PostTask(
- FROM_HERE, Bind(&MessageLoopProxyImplTest::BasicFunction,
- Unretained(this))));
- MessageLoop::current()->Run();
-}
-
-TEST_F(MessageLoopProxyImplTest, PostTaskAfterThreadExits) {
- scoped_ptr<Thread> test_thread(
- new Thread("MessageLoopProxyImplTest_Dummy"));
- test_thread->Start();
- scoped_refptr<MessageLoopProxy> message_loop_proxy =
- test_thread->message_loop_proxy();
- test_thread->Stop();
-
- bool ret = message_loop_proxy->PostTask(
- FROM_HERE,
- Bind(&MessageLoopProxyImplTest::AssertNotRun));
- EXPECT_FALSE(ret);
-}
-
-TEST_F(MessageLoopProxyImplTest, PostTaskAfterThreadIsDeleted) {
- scoped_refptr<MessageLoopProxy> message_loop_proxy;
- {
- scoped_ptr<Thread> test_thread(
- new Thread("MessageLoopProxyImplTest_Dummy"));
- test_thread->Start();
- message_loop_proxy = test_thread->message_loop_proxy();
- }
- bool ret = message_loop_proxy->PostTask(
- FROM_HERE,
- Bind(&MessageLoopProxyImplTest::AssertNotRun));
- EXPECT_FALSE(ret);
-}
-
-} // namespace base
diff --git a/base/message_loop/message_loop_proxy_unittest.cc b/base/message_loop/message_loop_proxy_unittest.cc
deleted file mode 100644
index 0b0d9f8..0000000
--- a/base/message_loop/message_loop_proxy_unittest.cc
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright (c) 2012 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_proxy.h"
-
-#include "base/atomic_sequence_num.h"
-#include "base/bind.h"
-#include "base/debug/leak_annotations.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class MessageLoopProxyTest : public testing::Test {
- public:
- MessageLoopProxyTest()
- : current_loop_(new MessageLoop()),
- task_thread_("task_thread"),
- thread_sync_(true, false) {
- }
-
- void DeleteCurrentMessageLoop() {
- current_loop_.reset();
- }
-
- protected:
- void SetUp() override {
- // Use SetUp() instead of the constructor to avoid posting a task to a
- // partialy constructed object.
- task_thread_.Start();
-
- // Allow us to pause the |task_thread_|'s MessageLoop.
- task_thread_.message_loop()->PostTask(
- FROM_HERE,
- Bind(&MessageLoopProxyTest::BlockTaskThreadHelper, Unretained(this)));
- }
-
- void TearDown() override {
- // Make sure the |task_thread_| is not blocked, and stop the thread
- // fully before destuction because its tasks may still depend on the
- // |thread_sync_| event.
- thread_sync_.Signal();
- task_thread_.Stop();
- DeleteCurrentMessageLoop();
- }
-
- // Make LoopRecorder threadsafe so that there is defined behavior even if a
- // threading mistake sneaks into the PostTaskAndReplyRelay implementation.
- class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> {
- public:
- LoopRecorder(MessageLoop** run_on, MessageLoop** deleted_on,
- int* destruct_order)
- : run_on_(run_on),
- deleted_on_(deleted_on),
- destruct_order_(destruct_order) {
- }
-
- void RecordRun() {
- *run_on_ = MessageLoop::current();
- }
-
- private:
- friend class RefCountedThreadSafe<LoopRecorder>;
- ~LoopRecorder() {
- *deleted_on_ = MessageLoop::current();
- *destruct_order_ = g_order.GetNext();
- }
-
- MessageLoop** run_on_;
- MessageLoop** deleted_on_;
- int* destruct_order_;
- };
-
- static void RecordLoop(scoped_refptr<LoopRecorder> recorder) {
- recorder->RecordRun();
- }
-
- static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) {
- recorder->RecordRun();
- MessageLoop::current()->QuitWhenIdle();
- }
-
- void UnblockTaskThread() {
- thread_sync_.Signal();
- }
-
- void BlockTaskThreadHelper() {
- thread_sync_.Wait();
- }
-
- static StaticAtomicSequenceNumber g_order;
-
- scoped_ptr<MessageLoop> current_loop_;
- Thread task_thread_;
-
- private:
- base::WaitableEvent thread_sync_;
-};
-
-StaticAtomicSequenceNumber MessageLoopProxyTest::g_order;
-
-TEST_F(MessageLoopProxyTest, PostTaskAndReply_Basic) {
- MessageLoop* task_run_on = NULL;
- MessageLoop* task_deleted_on = NULL;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = NULL;
- MessageLoop* reply_deleted_on = NULL;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recoder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recoder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- ASSERT_TRUE(task_thread_.message_loop_proxy()->PostTaskAndReply(
- FROM_HERE,
- Bind(&RecordLoop, task_recoder),
- Bind(&RecordLoopAndQuit, reply_recoder)));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recoder = NULL;
- reply_recoder = NULL;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- UnblockTaskThread();
- current_loop_->Run();
-
- EXPECT_EQ(task_thread_.message_loop(), task_run_on);
- EXPECT_EQ(current_loop_.get(), task_deleted_on);
- EXPECT_EQ(current_loop_.get(), reply_run_on);
- EXPECT_EQ(current_loop_.get(), reply_deleted_on);
- EXPECT_LT(task_delete_order, reply_delete_order);
-}
-
-TEST_F(MessageLoopProxyTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) {
- MessageLoop* task_run_on = NULL;
- MessageLoop* task_deleted_on = NULL;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = NULL;
- MessageLoop* reply_deleted_on = NULL;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recoder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recoder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Grab a MessageLoopProxy to a dead MessageLoop.
- scoped_refptr<MessageLoopProxy> task_loop_proxy =
- task_thread_.message_loop_proxy();
- UnblockTaskThread();
- task_thread_.Stop();
-
- ASSERT_FALSE(task_loop_proxy->PostTaskAndReply(
- FROM_HERE,
- Bind(&RecordLoop, task_recoder),
- Bind(&RecordLoopAndQuit, reply_recoder)));
-
- // The relay should have properly deleted its resources leaving us as the only
- // reference.
- EXPECT_EQ(task_delete_order, reply_delete_order);
- ASSERT_TRUE(task_recoder->HasOneRef());
- ASSERT_TRUE(reply_recoder->HasOneRef());
-
- // Nothing should have run though.
- EXPECT_FALSE(task_run_on);
- EXPECT_FALSE(reply_run_on);
-}
-
-TEST_F(MessageLoopProxyTest, PostTaskAndReply_SameLoop) {
- MessageLoop* task_run_on = NULL;
- MessageLoop* task_deleted_on = NULL;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = NULL;
- MessageLoop* reply_deleted_on = NULL;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recoder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recoder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Enqueue the relay.
- ASSERT_TRUE(current_loop_->message_loop_proxy()->PostTaskAndReply(
- FROM_HERE,
- Bind(&RecordLoop, task_recoder),
- Bind(&RecordLoopAndQuit, reply_recoder)));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recoder = NULL;
- reply_recoder = NULL;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- current_loop_->Run();
-
- EXPECT_EQ(current_loop_.get(), task_run_on);
- EXPECT_EQ(current_loop_.get(), task_deleted_on);
- EXPECT_EQ(current_loop_.get(), reply_run_on);
- EXPECT_EQ(current_loop_.get(), reply_deleted_on);
- EXPECT_LT(task_delete_order, reply_delete_order);
-}
-
-TEST_F(MessageLoopProxyTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) {
- // Annotate the scope as having memory leaks to suppress heapchecker reports.
- ANNOTATE_SCOPED_MEMORY_LEAK;
- MessageLoop* task_run_on = NULL;
- MessageLoop* task_deleted_on = NULL;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = NULL;
- MessageLoop* reply_deleted_on = NULL;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recoder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recoder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Enqueue the relay.
- task_thread_.message_loop_proxy()->PostTaskAndReply(
- FROM_HERE,
- Bind(&RecordLoop, task_recoder),
- Bind(&RecordLoopAndQuit, reply_recoder));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recoder = NULL;
- reply_recoder = NULL;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- UnblockTaskThread();
-
- // Mercilessly whack the current loop before |reply| gets to run.
- current_loop_.reset();
-
- // This should ensure the relay has been run. We need to record the
- // MessageLoop pointer before stopping the thread because Thread::Stop() will
- // NULL out its own pointer.
- MessageLoop* task_loop = task_thread_.message_loop();
- task_thread_.Stop();
-
- EXPECT_EQ(task_loop, task_run_on);
- ASSERT_FALSE(task_deleted_on);
- EXPECT_FALSE(reply_run_on);
- ASSERT_FALSE(reply_deleted_on);
- EXPECT_EQ(task_delete_order, reply_delete_order);
-
- // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to
- // it, we cannot just delete it because PostTaskAndReplyRelay's destructor
- // checks that MessageLoop::current() is the the same as when the
- // PostTaskAndReplyRelay object was constructed. However, this loop must have
- // aleady been deleted in order to perform this test. See
- // http://crbug.com/86301.
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/message_loop/message_loop_proxy_impl.cc b/base/message_loop/message_loop_task_runner.cc
similarity index 62%
rename from base/message_loop/message_loop_proxy_impl.cc
rename to base/message_loop/message_loop_task_runner.cc
index 580620d..c9b5ffe 100644
--- a/base/message_loop/message_loop_proxy_impl.cc
+++ b/base/message_loop/message_loop_task_runner.cc
@@ -2,29 +2,27 @@
// 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_proxy_impl.h"
+#include "base/message_loop/message_loop_task_runner.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/incoming_task_queue.h"
-#include "base/message_loop/message_loop.h"
namespace base {
namespace internal {
-MessageLoopProxyImpl::MessageLoopProxyImpl(
+MessageLoopTaskRunner::MessageLoopTaskRunner(
scoped_refptr<IncomingTaskQueue> incoming_queue)
- : incoming_queue_(incoming_queue),
- valid_thread_id_(kInvalidThreadId) {
+ : incoming_queue_(incoming_queue), valid_thread_id_(kInvalidThreadId) {
}
-void MessageLoopProxyImpl::BindToCurrentThread() {
+void MessageLoopTaskRunner::BindToCurrentThread() {
AutoLock lock(valid_thread_id_lock_);
DCHECK_EQ(kInvalidThreadId, valid_thread_id_);
valid_thread_id_ = PlatformThread::CurrentId();
}
-bool MessageLoopProxyImpl::PostDelayedTask(
+bool MessageLoopTaskRunner::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
@@ -32,7 +30,7 @@
return incoming_queue_->AddToIncomingQueue(from_here, task, delay, true);
}
-bool MessageLoopProxyImpl::PostNonNestableDelayedTask(
+bool MessageLoopTaskRunner::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
@@ -40,22 +38,14 @@
return incoming_queue_->AddToIncomingQueue(from_here, task, delay, false);
}
-bool MessageLoopProxyImpl::RunsTasksOnCurrentThread() const {
+bool MessageLoopTaskRunner::RunsTasksOnCurrentThread() const {
AutoLock lock(valid_thread_id_lock_);
return valid_thread_id_ == PlatformThread::CurrentId();
}
-MessageLoopProxyImpl::~MessageLoopProxyImpl() {
+MessageLoopTaskRunner::~MessageLoopTaskRunner() {
}
} // namespace internal
-scoped_refptr<MessageLoopProxy>
-MessageLoopProxy::current() {
- MessageLoop* cur_loop = MessageLoop::current();
- if (!cur_loop)
- return NULL;
- return cur_loop->message_loop_proxy();
-}
-
} // namespace base
diff --git a/base/message_loop/message_loop_proxy_impl.h b/base/message_loop/message_loop_task_runner.h
similarity index 60%
rename from base/message_loop/message_loop_proxy_impl.h
rename to base/message_loop/message_loop_task_runner.h
index fa611c2..dc2947d 100644
--- a/base/message_loop/message_loop_proxy_impl.h
+++ b/base/message_loop/message_loop_task_runner.h
@@ -2,13 +2,13 @@
// 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_PROXY_IMPL_H_
-#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_IMPL_H_
+#ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_
#include "base/base_export.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "base/pending_task.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
@@ -17,18 +17,18 @@
class IncomingTaskQueue;
-// A stock implementation of MessageLoopProxy that is created and managed by a
-// MessageLoop. For now a MessageLoopProxyImpl can only be created as part of a
-// MessageLoop.
-class BASE_EXPORT MessageLoopProxyImpl : public MessageLoopProxy {
+// A stock implementation of SingleThreadTaskRunner that is created and managed
+// by a MessageLoop. For now a MessageLoopTaskRunner can only be created as
+// part of a MessageLoop.
+class BASE_EXPORT MessageLoopTaskRunner : public SingleThreadTaskRunner {
public:
- explicit MessageLoopProxyImpl(
+ explicit MessageLoopTaskRunner(
scoped_refptr<IncomingTaskQueue> incoming_queue);
- // Initialize this message loop proxy on the current thread.
+ // Initialize this message loop task runner on the current thread.
void BindToCurrentThread();
- // MessageLoopProxy implementation
+ // SingleThreadTaskRunner implementation
bool PostDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) override;
@@ -38,10 +38,10 @@
bool RunsTasksOnCurrentThread() const override;
private:
- friend class RefCountedThreadSafe<MessageLoopProxyImpl>;
- ~MessageLoopProxyImpl() override;
+ friend class RefCountedThreadSafe<MessageLoopTaskRunner>;
+ ~MessageLoopTaskRunner() override;
- // THe incoming queue receiving all posted tasks.
+ // The incoming queue receiving all posted tasks.
scoped_refptr<IncomingTaskQueue> incoming_queue_;
// ID of the thread |this| was created on. Could be accessed on multiple
@@ -49,10 +49,10 @@
PlatformThreadId valid_thread_id_;
mutable Lock valid_thread_id_lock_;
- DISALLOW_COPY_AND_ASSIGN(MessageLoopProxyImpl);
+ DISALLOW_COPY_AND_ASSIGN(MessageLoopTaskRunner);
};
} // namespace internal
} // namespace base
-#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_PROXY_IMPL_H_
+#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_
diff --git a/base/message_loop/message_loop_task_runner_unittest.cc b/base/message_loop/message_loop_task_runner_unittest.cc
new file mode 100644
index 0000000..caf88af
--- /dev/null
+++ b/base/message_loop/message_loop_task_runner_unittest.cc
@@ -0,0 +1,358 @@
+// Copyright (c) 2012 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_task_runner.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/bind.h"
+#include "base/debug/leak_annotations.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace base {
+
+class MessageLoopTaskRunnerTest : public testing::Test {
+ public:
+ MessageLoopTaskRunnerTest()
+ : current_loop_(new MessageLoop()),
+ task_thread_("task_thread"),
+ thread_sync_(true, false) {}
+
+ void DeleteCurrentMessageLoop() { current_loop_.reset(); }
+
+ protected:
+ void SetUp() override {
+ // Use SetUp() instead of the constructor to avoid posting a task to a
+ // partialy constructed object.
+ task_thread_.Start();
+
+ // Allow us to pause the |task_thread_|'s MessageLoop.
+ task_thread_.message_loop()->PostTask(
+ FROM_HERE, Bind(&MessageLoopTaskRunnerTest::BlockTaskThreadHelper,
+ Unretained(this)));
+ }
+
+ void TearDown() override {
+ // Make sure the |task_thread_| is not blocked, and stop the thread
+ // fully before destuction because its tasks may still depend on the
+ // |thread_sync_| event.
+ thread_sync_.Signal();
+ task_thread_.Stop();
+ DeleteCurrentMessageLoop();
+ }
+
+ // Make LoopRecorder threadsafe so that there is defined behavior even if a
+ // threading mistake sneaks into the PostTaskAndReplyRelay implementation.
+ class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> {
+ public:
+ LoopRecorder(MessageLoop** run_on,
+ MessageLoop** deleted_on,
+ int* destruct_order)
+ : run_on_(run_on),
+ deleted_on_(deleted_on),
+ destruct_order_(destruct_order) {}
+
+ void RecordRun() { *run_on_ = MessageLoop::current(); }
+
+ private:
+ friend class RefCountedThreadSafe<LoopRecorder>;
+ ~LoopRecorder() {
+ *deleted_on_ = MessageLoop::current();
+ *destruct_order_ = g_order.GetNext();
+ }
+
+ MessageLoop** run_on_;
+ MessageLoop** deleted_on_;
+ int* destruct_order_;
+ };
+
+ static void RecordLoop(scoped_refptr<LoopRecorder> recorder) {
+ recorder->RecordRun();
+ }
+
+ static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) {
+ recorder->RecordRun();
+ MessageLoop::current()->QuitWhenIdle();
+ }
+
+ void UnblockTaskThread() { thread_sync_.Signal(); }
+
+ void BlockTaskThreadHelper() { thread_sync_.Wait(); }
+
+ static StaticAtomicSequenceNumber g_order;
+
+ scoped_ptr<MessageLoop> current_loop_;
+ Thread task_thread_;
+
+ private:
+ base::WaitableEvent thread_sync_;
+};
+
+StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order;
+
+TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) {
+ MessageLoop* task_run_on = NULL;
+ MessageLoop* task_deleted_on = NULL;
+ int task_delete_order = -1;
+ MessageLoop* reply_run_on = NULL;
+ MessageLoop* reply_deleted_on = NULL;
+ int reply_delete_order = -1;
+
+ scoped_refptr<LoopRecorder> task_recoder =
+ new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
+ scoped_refptr<LoopRecorder> reply_recoder =
+ new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
+
+ ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply(
+ FROM_HERE, Bind(&RecordLoop, task_recoder),
+ Bind(&RecordLoopAndQuit, reply_recoder)));
+
+ // Die if base::Bind doesn't retain a reference to the recorders.
+ task_recoder = NULL;
+ reply_recoder = NULL;
+ ASSERT_FALSE(task_deleted_on);
+ ASSERT_FALSE(reply_deleted_on);
+
+ UnblockTaskThread();
+ current_loop_->Run();
+
+ EXPECT_EQ(task_thread_.message_loop(), task_run_on);
+ EXPECT_EQ(current_loop_.get(), task_deleted_on);
+ EXPECT_EQ(current_loop_.get(), reply_run_on);
+ EXPECT_EQ(current_loop_.get(), reply_deleted_on);
+ EXPECT_LT(task_delete_order, reply_delete_order);
+}
+
+TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) {
+ MessageLoop* task_run_on = NULL;
+ MessageLoop* task_deleted_on = NULL;
+ int task_delete_order = -1;
+ MessageLoop* reply_run_on = NULL;
+ MessageLoop* reply_deleted_on = NULL;
+ int reply_delete_order = -1;
+
+ scoped_refptr<LoopRecorder> task_recoder =
+ new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
+ scoped_refptr<LoopRecorder> reply_recoder =
+ new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
+
+ // Grab a task runner to a dead MessageLoop.
+ scoped_refptr<SingleThreadTaskRunner> task_runner =
+ task_thread_.task_runner();
+ UnblockTaskThread();
+ task_thread_.Stop();
+
+ ASSERT_FALSE(
+ task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recoder),
+ Bind(&RecordLoopAndQuit, reply_recoder)));
+
+ // The relay should have properly deleted its resources leaving us as the only
+ // reference.
+ EXPECT_EQ(task_delete_order, reply_delete_order);
+ ASSERT_TRUE(task_recoder->HasOneRef());
+ ASSERT_TRUE(reply_recoder->HasOneRef());
+
+ // Nothing should have run though.
+ EXPECT_FALSE(task_run_on);
+ EXPECT_FALSE(reply_run_on);
+}
+
+TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) {
+ MessageLoop* task_run_on = NULL;
+ MessageLoop* task_deleted_on = NULL;
+ int task_delete_order = -1;
+ MessageLoop* reply_run_on = NULL;
+ MessageLoop* reply_deleted_on = NULL;
+ int reply_delete_order = -1;
+
+ scoped_refptr<LoopRecorder> task_recoder =
+ new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
+ scoped_refptr<LoopRecorder> reply_recoder =
+ new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
+
+ // Enqueue the relay.
+ ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply(
+ FROM_HERE, Bind(&RecordLoop, task_recoder),
+ Bind(&RecordLoopAndQuit, reply_recoder)));
+
+ // Die if base::Bind doesn't retain a reference to the recorders.
+ task_recoder = NULL;
+ reply_recoder = NULL;
+ ASSERT_FALSE(task_deleted_on);
+ ASSERT_FALSE(reply_deleted_on);
+
+ current_loop_->Run();
+
+ EXPECT_EQ(current_loop_.get(), task_run_on);
+ EXPECT_EQ(current_loop_.get(), task_deleted_on);
+ EXPECT_EQ(current_loop_.get(), reply_run_on);
+ EXPECT_EQ(current_loop_.get(), reply_deleted_on);
+ EXPECT_LT(task_delete_order, reply_delete_order);
+}
+
+TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) {
+ // Annotate the scope as having memory leaks to suppress heapchecker reports.
+ ANNOTATE_SCOPED_MEMORY_LEAK;
+ MessageLoop* task_run_on = NULL;
+ MessageLoop* task_deleted_on = NULL;
+ int task_delete_order = -1;
+ MessageLoop* reply_run_on = NULL;
+ MessageLoop* reply_deleted_on = NULL;
+ int reply_delete_order = -1;
+
+ scoped_refptr<LoopRecorder> task_recoder =
+ new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
+ scoped_refptr<LoopRecorder> reply_recoder =
+ new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
+
+ // Enqueue the relay.
+ task_thread_.task_runner()->PostTaskAndReply(
+ FROM_HERE, Bind(&RecordLoop, task_recoder),
+ Bind(&RecordLoopAndQuit, reply_recoder));
+
+ // Die if base::Bind doesn't retain a reference to the recorders.
+ task_recoder = NULL;
+ reply_recoder = NULL;
+ ASSERT_FALSE(task_deleted_on);
+ ASSERT_FALSE(reply_deleted_on);
+
+ UnblockTaskThread();
+
+ // Mercilessly whack the current loop before |reply| gets to run.
+ current_loop_.reset();
+
+ // This should ensure the relay has been run. We need to record the
+ // MessageLoop pointer before stopping the thread because Thread::Stop() will
+ // NULL out its own pointer.
+ MessageLoop* task_loop = task_thread_.message_loop();
+ task_thread_.Stop();
+
+ EXPECT_EQ(task_loop, task_run_on);
+ ASSERT_FALSE(task_deleted_on);
+ EXPECT_FALSE(reply_run_on);
+ ASSERT_FALSE(reply_deleted_on);
+ EXPECT_EQ(task_delete_order, reply_delete_order);
+
+ // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to
+ // it, we cannot just delete it because PostTaskAndReplyRelay's destructor
+ // checks that MessageLoop::current() is the the same as when the
+ // PostTaskAndReplyRelay object was constructed. However, this loop must have
+ // aleady been deleted in order to perform this test. See
+ // http://crbug.com/86301.
+}
+
+class MessageLoopTaskRunnerThreadingTest : public testing::Test {
+ public:
+ void Release() const {
+ AssertOnIOThread();
+ Quit();
+ }
+
+ void Quit() const {
+ loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure());
+ }
+
+ void AssertOnIOThread() const {
+ ASSERT_TRUE(io_thread_->task_runner()->BelongsToCurrentThread());
+ ASSERT_EQ(io_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
+ }
+
+ void AssertOnFileThread() const {
+ ASSERT_TRUE(file_thread_->task_runner()->BelongsToCurrentThread());
+ ASSERT_EQ(file_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
+ }
+
+ protected:
+ void SetUp() override {
+ io_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_IO"));
+ file_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_File"));
+ io_thread_->Start();
+ file_thread_->Start();
+ }
+
+ void TearDown() override {
+ io_thread_->Stop();
+ file_thread_->Stop();
+ }
+
+ static void BasicFunction(MessageLoopTaskRunnerThreadingTest* test) {
+ test->AssertOnFileThread();
+ test->Quit();
+ }
+
+ static void AssertNotRun() { FAIL() << "Callback Should not get executed."; }
+
+ class DeletedOnFile {
+ public:
+ explicit DeletedOnFile(MessageLoopTaskRunnerThreadingTest* test)
+ : test_(test) {}
+
+ ~DeletedOnFile() {
+ test_->AssertOnFileThread();
+ test_->Quit();
+ }
+
+ private:
+ MessageLoopTaskRunnerThreadingTest* test_;
+ };
+
+ scoped_ptr<Thread> io_thread_;
+ scoped_ptr<Thread> file_thread_;
+
+ private:
+ mutable MessageLoop loop_;
+};
+
+TEST_F(MessageLoopTaskRunnerThreadingTest, Release) {
+ EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this));
+ MessageLoop::current()->Run();
+}
+
+TEST_F(MessageLoopTaskRunnerThreadingTest, Delete) {
+ DeletedOnFile* deleted_on_file = new DeletedOnFile(this);
+ EXPECT_TRUE(
+ file_thread_->task_runner()->DeleteSoon(FROM_HERE, deleted_on_file));
+ MessageLoop::current()->Run();
+}
+
+TEST_F(MessageLoopTaskRunnerThreadingTest, PostTask) {
+ EXPECT_TRUE(file_thread_->task_runner()->PostTask(
+ FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::BasicFunction,
+ Unretained(this))));
+ MessageLoop::current()->Run();
+}
+
+TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadExits) {
+ scoped_ptr<Thread> test_thread(
+ new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
+ test_thread->Start();
+ scoped_refptr<SingleThreadTaskRunner> task_runner =
+ test_thread->task_runner();
+ test_thread->Stop();
+
+ bool ret = task_runner->PostTask(
+ FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
+ EXPECT_FALSE(ret);
+}
+
+TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadIsDeleted) {
+ scoped_refptr<SingleThreadTaskRunner> task_runner;
+ {
+ scoped_ptr<Thread> test_thread(
+ new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
+ test_thread->Start();
+ task_runner = test_thread->task_runner();
+ }
+ bool ret = task_runner->PostTask(
+ FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
+ EXPECT_FALSE(ret);
+}
+
+} // namespace base
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index ddde6bb..48c82c4 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy_impl.h"
#include "base/message_loop/message_loop_test.h"
#include "base/pending_task.h"
#include "base/posix/eintr_wrapper.h"