summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-03 22:34:17 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-03 22:34:17 +0000
commitd53e6a6c73062427e7408cf4cb156938ac509311 (patch)
treee98959728b1d1ab9717753b3b6189f7bd375c034 /base
parent3f24ae2243c95d0907a4447b799b37e8569650a0 (diff)
downloadchromium_src-d53e6a6c73062427e7408cf4cb156938ac509311.zip
chromium_src-d53e6a6c73062427e7408cf4cb156938ac509311.tar.gz
chromium_src-d53e6a6c73062427e7408cf4cb156938ac509311.tar.bz2
When using PostTaskAndReplyWithResults, if the ResultType is a passed type (eg: scoped_ptr and friends), .Pass() the result to the reply.
Because the temporary storage of the result is an implementation detail of PostTaskAndReplyWithResults, its safe to always assume that passed types should be passed. BUG=126008 TEST=TaskRunnerHelpersTest.PostTaskAndReplyWithResultPassed Review URL: http://codereview.chromium.org/10344012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135228 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/callback_internal.h5
-rw-r--r--base/task_runner_util.h3
-rw-r--r--base/task_runner_util_unittest.cc37
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