summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authordcheng <dcheng@chromium.org>2015-12-14 12:31:52 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-14 20:33:25 +0000
commit69f2a0417b06343a0f3241e7d87bd78ca3849ca7 (patch)
tree395092f0d3debba844a91aeb52b5b34f9dc9b03e /base
parente1504e2e6888ef6ab7ae7e5760f8688a47d78b72 (diff)
downloadchromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.zip
chromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.tar.gz
chromium_src-69f2a0417b06343a0f3241e7d87bd78ca3849ca7.tar.bz2
Compatibility shim to allow std::unique_ptr use with base::Callback.
BUG=554298,561749 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1494373002 Cr-Commit-Position: refs/heads/master@{#365087}
Diffstat (limited to 'base')
-rw-r--r--base/bind_unittest.cc48
-rw-r--r--base/callback_internal.h14
2 files changed, 60 insertions, 2 deletions
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index f885403..afa523c 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -4,6 +4,9 @@
#include "base/bind.h"
+#include <memory>
+#include <utility>
+
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -150,7 +153,7 @@ class DeleteCounter {
template <typename T>
T PassThru(T scoper) {
- return scoper.Pass();
+ return scoper;
}
// Some test functions that we can Bind to.
@@ -752,6 +755,49 @@ TEST_F(BindTest, ScopedPtr) {
cb_unbound.Run(ptr.Pass());
}
+TEST_F(BindTest, UniquePtr) {
+ int deletes = 0;
+
+ // Tests the Passed() function's support for pointers.
+ std::unique_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
+ Callback<std::unique_ptr<DeleteCounter>(void)> unused_callback =
+ Bind(&PassThru<std::unique_ptr<DeleteCounter>>, Passed(&ptr));
+ EXPECT_FALSE(ptr.get());
+ EXPECT_EQ(0, deletes);
+
+ // If we never invoke the Callback, it retains ownership and deletes.
+ unused_callback.Reset();
+ EXPECT_EQ(1, deletes);
+
+ // Tests the Passed() function's support for rvalues.
+ deletes = 0;
+ DeleteCounter* counter = new DeleteCounter(&deletes);
+ Callback<std::unique_ptr<DeleteCounter>(void)> callback =
+ Bind(&PassThru<std::unique_ptr<DeleteCounter>>,
+ Passed(std::unique_ptr<DeleteCounter>(counter)));
+ EXPECT_FALSE(ptr.get());
+ EXPECT_EQ(0, deletes);
+
+ // Check that ownership can be transferred back out.
+ std::unique_ptr<DeleteCounter> result = callback.Run();
+ ASSERT_EQ(counter, result.get());
+ EXPECT_EQ(0, deletes);
+
+ // Resetting does not delete since ownership was transferred.
+ callback.Reset();
+ EXPECT_EQ(0, deletes);
+
+ // Ensure that we actually did get ownership.
+ result.reset();
+ EXPECT_EQ(1, deletes);
+
+ // Test unbound argument forwarding.
+ Callback<std::unique_ptr<DeleteCounter>(std::unique_ptr<DeleteCounter>)>
+ cb_unbound = Bind(&PassThru<std::unique_ptr<DeleteCounter>>);
+ ptr.reset(new DeleteCounter(&deletes));
+ cb_unbound.Run(std::move(ptr));
+}
+
// Argument Copy-constructor usage for non-reference parameters.
// - Bound arguments are only copied once.
// - Forwarded arguments are only copied once.
diff --git a/base/callback_internal.h b/base/callback_internal.h
index aa8542c..a2adbf9 100644
--- a/base/callback_internal.h
+++ b/base/callback_internal.h
@@ -9,6 +9,7 @@
#define BASE_CALLBACK_INTERNAL_H_
#include <stddef.h>
+#include <memory>
#include <type_traits>
#include "base/atomic_ref_count.h"
@@ -94,7 +95,13 @@ class BASE_EXPORT CallbackBase {
// A helper template to determine if given type is non-const move-only-type,
// i.e. if a value of the given type should be passed via std::move() in a
-// destructive way.
+// destructive way. Types are considered to be move-only if they have a
+// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using
+// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro.
+// It would be easy to generalize this trait to all move-only types... but this
+// confuses template deduction in VS2013 with certain types such as
+// std::unique_ptr.
+// TODO(dcheng): Revisit this when Windows switches to VS2015 by default.
template <typename T> struct IsMoveOnlyType {
template <typename U>
static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
@@ -106,6 +113,11 @@ template <typename T> struct IsMoveOnlyType {
!is_const<T>::value;
};
+// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered
+// move-only, even without the sentinel member.
+template <typename T>
+struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {};
+
template <typename>
struct CallbackParamTraitsForMoveOnlyType;