summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gypi2
-rw-r--r--base/message_loop.cc5
-rw-r--r--base/message_loop.h4
-rw-r--r--base/message_loop_unittest.cc23
-rw-r--r--base/thread_task_runner_handle.cc41
-rw-r--r--base/thread_task_runner_handle.h35
6 files changed, 109 insertions, 1 deletions
diff --git a/base/base.gypi b/base/base.gypi
index c19658f..897cabd 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -348,6 +348,8 @@
'task_runner.h',
'task_runner_util.h',
'template_util.h',
+ 'thread_task_runner_handle.cc',
+ 'thread_task_runner_handle.h',
'threading/non_thread_safe.h',
'threading/non_thread_safe_impl.cc',
'threading/non_thread_safe_impl.h',
diff --git a/base/message_loop.cc b/base/message_loop.cc
index f60bf69..dd8ba3a 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -17,6 +17,7 @@
#include "base/message_pump_default.h"
#include "base/metrics/histogram.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_local.h"
#include "base/time.h"
#include "base/tracked_objects.h"
@@ -139,6 +140,8 @@ MessageLoop::MessageLoop(Type type)
lazy_tls_ptr.Pointer()->Set(this);
message_loop_proxy_ = new base::MessageLoopProxyImpl();
+ thread_task_runner_handle_.reset(
+ new base::ThreadTaskRunnerHandle(message_loop_proxy_));
// TODO(rvargas): Get rid of the OS guards.
#if defined(OS_WIN)
@@ -198,6 +201,8 @@ MessageLoop::~MessageLoop() {
FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
WillDestroyCurrentMessageLoop());
+ thread_task_runner_handle_.reset();
+
// Tell the message_loop_proxy that we are dying.
static_cast<base::MessageLoopProxyImpl*>(message_loop_proxy_.get())->
WillDestroyCurrentMessageLoop();
diff --git a/base/message_loop.h b/base/message_loop.h
index c1ffc89..ef8d59f 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -42,7 +42,8 @@
namespace base {
class Histogram;
-}
+class ThreadTaskRunnerHandle;
+} // namespace base
// A MessageLoop is used to process events for a particular thread. There is
// at most one MessageLoop instance per thread.
@@ -519,6 +520,7 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
// The message loop proxy associated with this message loop, if one exists.
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
private:
template <class T, class R> friend class base::subtle::DeleteHelperInternal;
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index 15f825b..7167c5e 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -1689,3 +1690,25 @@ TEST(MessageLoopTest, DestructionObserverTest) {
EXPECT_TRUE(task_destroyed);
EXPECT_TRUE(destruction_observer_called);
}
+
+
+// Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
+// posts tasks on that message loop.
+TEST(MessageLoopTest, ThreadMainTaskRunner) {
+ MessageLoop loop;
+
+ scoped_refptr<Foo> foo(new Foo());
+ std::string a("a");
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
+ &Foo::Test1ConstRef, foo.get(), a));
+
+ // Post quit task;
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
+
+ // Now kick things off
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(foo->test_count(), 1);
+ EXPECT_EQ(foo->result(), "a");
+}
diff --git a/base/thread_task_runner_handle.cc b/base/thread_task_runner_handle.cc
new file mode 100644
index 0000000..d1b07aa
--- /dev/null
+++ b/base/thread_task_runner_handle.cc
@@ -0,0 +1,41 @@
+// 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/thread_task_runner_handle.h"
+
+#include "base/lazy_instance.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+
+namespace {
+
+base::LazyInstance<base::ThreadLocalPointer<ThreadTaskRunnerHandle> >
+ lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// static
+scoped_refptr<SingleThreadTaskRunner> ThreadTaskRunnerHandle::Get() {
+ ThreadTaskRunnerHandle* current = lazy_tls_ptr.Pointer()->Get();
+ DCHECK(current);
+ return current->task_runner_;
+}
+
+ThreadTaskRunnerHandle::ThreadTaskRunnerHandle(
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner)
+ : task_runner_(task_runner) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ lazy_tls_ptr.Pointer()->Set(this);
+}
+
+ThreadTaskRunnerHandle::~ThreadTaskRunnerHandle() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(lazy_tls_ptr.Pointer()->Get(), this);
+ lazy_tls_ptr.Pointer()->Set(NULL);
+}
+
+} // namespace base
diff --git a/base/thread_task_runner_handle.h b/base/thread_task_runner_handle.h
new file mode 100644
index 0000000..599d15b
--- /dev/null
+++ b/base/thread_task_runner_handle.h
@@ -0,0 +1,35 @@
+// 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_THREAD_TASK_RUNNER_HANDLE_H_
+#define BASE_THREAD_TASK_RUNNER_HANDLE_H_
+
+#include "base/base_export.h"
+#include "base/memory/ref_counted.h"
+
+namespace base {
+
+class SingleThreadTaskRunner;
+
+// ThreadTaskRunnerHandle stores a reference to the main task runner
+// for each thread. Not more than one of these objects can be created
+// per thread. After an instance of this object is created the Get()
+// function will return the |task_runner| specified in the
+// constructor.
+class BASE_EXPORT ThreadTaskRunnerHandle {
+ public:
+ // Gets the SingleThreadTaskRunner for the current thread.
+ static scoped_refptr<SingleThreadTaskRunner> Get();
+
+ ThreadTaskRunnerHandle(
+ const scoped_refptr<SingleThreadTaskRunner>& task_runner);
+ ~ThreadTaskRunnerHandle();
+
+ private:
+ scoped_refptr<SingleThreadTaskRunner> task_runner_;
+};
+
+} // namespace base
+
+#endif // BASE_THREAD_TASK_RUNNER_HANDLE_H_