diff options
-rw-r--r-- | base/callback_internal.h | 5 | ||||
-rw-r--r-- | base/task_runner_util.h | 3 | ||||
-rw-r--r-- | base/task_runner_util_unittest.cc | 37 |
3 files changed, 43 insertions, 2 deletions
diff --git a/base/callback_internal.h b/base/callback_internal.h index 244504b..92ea80a 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -166,6 +166,11 @@ struct CallbackParamTraits<ScopedVector<T> > { // In C++11, std::forward would replace all uses of this function. However, it // is impossible to implement a general std::forward with C++11 due to a lack // of rvalue references. +// +// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to +// simulate std::forward() and forward the result of one Callback as a +// parameter to another callback. This is to support Callbacks that return +// the movable-but-not-copyable types whitelisted above. template <typename T> T& CallbackForward(T& t) { return t; } diff --git a/base/task_runner_util.h b/base/task_runner_util.h index 9d20ef2..67e223e 100644 --- a/base/task_runner_util.h +++ b/base/task_runner_util.h @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback_internal.h" #include "base/logging.h" #include "base/task_runner.h" @@ -37,7 +38,7 @@ void ReplyAdapter(const Callback<void(ReturnType)>& callback, ReturnType* result) { DCHECK(result); if(!callback.is_null()) - callback.Run(*result); + callback.Run(CallbackForward(*result)); } // Helper class for TaskRunner::PostTaskAndReplyWithResult. diff --git a/base/task_runner_util_unittest.cc b/base/task_runner_util_unittest.cc index 4c58826..daed770 100644 --- a/base/task_runner_util_unittest.cc +++ b/base/task_runner_util_unittest.cc @@ -20,9 +20,28 @@ void StoreValue(int* destination, int value) { *destination = value; } +int g_foo_destruct_count = 0; + +struct Foo { + ~Foo() { + ++g_foo_destruct_count; + } +}; + +scoped_ptr<Foo> CreateFoo() { + return scoped_ptr<Foo>(new Foo); +} + +void ExpectFoo(scoped_ptr<Foo> foo) { + EXPECT_TRUE(foo.get()); + scoped_ptr<Foo> local_foo(foo.Pass()); + EXPECT_TRUE(local_foo.get()); + EXPECT_FALSE(foo.get()); +} + } // namespace -TEST(TaskRunnerHelpersTest, PostAndReplyWithStatus) { +TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResult) { MessageLoop message_loop; int result = 0; @@ -37,4 +56,20 @@ TEST(TaskRunnerHelpersTest, PostAndReplyWithStatus) { EXPECT_EQ(42, result); } +TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResultPassed) { + g_foo_destruct_count = 0; + + MessageLoop message_loop; + + PostTaskAndReplyWithResult( + message_loop.message_loop_proxy(), + FROM_HERE, + Bind(&CreateFoo), + Bind(&ExpectFoo)); + + message_loop.RunAllPending(); + + EXPECT_EQ(1, g_foo_destruct_count); +} + } // namespace base |