diff options
-rw-r--r-- | base/base.gypi | 2 | ||||
-rw-r--r-- | base/message_loop.cc | 5 | ||||
-rw-r--r-- | base/message_loop.h | 4 | ||||
-rw-r--r-- | base/message_loop_unittest.cc | 23 | ||||
-rw-r--r-- | base/thread_task_runner_handle.cc | 41 | ||||
-rw-r--r-- | base/thread_task_runner_handle.h | 35 |
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_ |