Index: base/bind_helpers.h |
diff --git a/base/bind_helpers.h b/base/bind_helpers.h |
index 6e0f8fe72742a06f7875d5f73a4b9e0ec97f6c45..df8cf82bca5994f41db931999410f0223040642c 100644 |
--- a/base/bind_helpers.h |
+++ b/base/bind_helpers.h |
@@ -6,19 +6,29 @@ |
// can be used specify the refcounting and reference semantics of arguments |
// that are bound by the Bind() function in base/bind.h. |
// |
-// The public functions are base::Unretained(), base::Owned(), |
-// base::ConstRef(), and base::IgnoreReturn(). |
+// The public functions are base::Unretained(), base::Owned(), bass::Passed(), |
+// base::ConstRef(), and base::IgnoreResult(). |
// |
// Unretained() allows Bind() to bind a non-refcounted class, and to disable |
// refcounting on arguments that are refcounted objects. |
+// |
// Owned() transfers ownership of an object to the Callback resulting from |
// bind; the object will be deleted when the Callback is deleted. |
+// |
+// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) |
+// through a Callback. Logically, this signifies a destructive transfer of |
+// the state of the argument into the target function. Invoking |
+// Callback::Run() twice on a Callback that was created with a Passed() |
+// argument will CHECK() because the first invocation would have already |
+// transferred ownership to the target function. |
+// |
// ConstRef() allows binding a constant reference to an argument rather |
// than a copy. |
-// IgnoreReturn() is used to adapt a 0-argument Callback with a return type to |
-// a Closure. This is useful if you need to PostTask with a function that has |
-// a return value that you don't care about. |
// |
+// IgnoreResult() is used to adapt a function or Callback with a return type to |
+// one with a void return. This is most useful if you have a function with, |
+// say, a pesky ignorable bool return that you want to use with PostTask or |
+// something else that expect a Callback with a void return. |
// |
// EXAMPLE OF Unretained(): |
// |
@@ -75,13 +85,45 @@ |
// its bound callbacks. |
// |
// |
-// EXAMPLE OF IgnoreReturn(): |
+// EXAMPLE OF IgnoreResult(): |
// |
// int DoSomething(int arg) { cout << arg << endl; } |
-// Callback<int(void)> cb = Bind(&DoSomething, 1); |
-// Closure c = IgnoreReturn(cb); // Prints "1" |
-// or |
-// ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| |
+// |
+// // Assign to a Callback with a void return type. |
+// Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething)); |
+// cb->Run(1); // Prints "1". |
+// |
+// // Prints "1" on |ml|. |
+// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); |
+// |
+// |
+// EXAMPLE OF Passed(): |
+// |
+// void TakesOwnership(scoped_ptr<Foo> arg) { } |
+// scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } |
+// |
+// scoped_ptr<Foo> f(new Foo()); |
+// |
+// // |cb| is given ownership of Foo(). |f| is now NULL. |
+// // You can use f.Pass() in place of &f, but it's more verbose. |
+// Closure cb = Bind(&TakesOwnership, Passed(&f)); |
+// |
+// // Run was never called so |cb| still owns Foo() and deletes |
+// // it on Reset(). |
+// cb.Reset(); |
+// |
+// // |cb| is given a new Foo created by CreateFoo(). |
+// cb = Bind(&TakesOwnership, Passed(CreateFoo())); |
+// |
+// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| |
+// // no longer owns Foo() and, if reset, would not delete Foo(). |
+// cb.Run(); // Foo() is now transferred to |arg| and deleted. |
+// cb.Run(); // This CHECK()s since Foo() already been used once. |
+// |
+// Passed() is particularly useful with PostTask() when you are transferring |
+// ownership of an argument into a task, but don't necessarily know if the |
+// task will always be executed. This can happen if the task is cancellable |
+// or if it is posted to a MessageLoopProxy. |
#ifndef BASE_BIND_HELPERS_H_ |
#define BASE_BIND_HELPERS_H_ |
@@ -287,6 +329,45 @@ class OwnedWrapper { |
mutable T* ptr_; |
}; |
+// PassedWrapper is a copyable adapter for a scoper that ignores const. |
+// |
+// It is needed to get around the fact that Bind() takes a const reference to |
+// all its arguments. Because Bind() takes a const reference to avoid |
+// unnecessary copies, it is incompatible with movable-but-not-copyable |
+// types; doing a destructive "move" of the type into Bind() would violate |
+// the const correctness. |
+// |
+// This conundrum cannot be solved without either C++11 rvalue references or |
+// a O(2^n) blowup of Bind() templates to handle each combination of regular |
+// types and movable-but-not-copyable types. Thus we introduce a wrapper type |
+// that is copyable to transmit the correct type information down into |
+// BindState<>. Ignoring const in this type makes sense because it is only |
+// created when we are explicitly trying to do a destructive move. |
+// |
+// Two notes: |
+// 1) PassedWrapper supports any type that has a "Pass()" function. |
+// This is intentional. The whitelisting of which specific types we |
+// support is maintained by CallbackParamTraits<>. |
+// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" |
+// scoper to a Callback and allow the Callback to execute once. |
+template <typename T> |
+class PassedWrapper { |
+ public: |
+ explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} |
+ PassedWrapper(const PassedWrapper& other) |
+ : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { |
+ } |
+ T Pass() const { |
+ CHECK(is_valid_); |
+ is_valid_ = false; |
+ return scoper_.Pass(); |
+ } |
+ |
+ private: |
+ mutable bool is_valid_; |
+ mutable T scoper_; |
+}; |
+ |
// Unwrap the stored parameters for the wrappers above. |
template <typename T> |
struct UnwrapTraits { |
@@ -330,9 +411,17 @@ struct UnwrapTraits<OwnedWrapper<T> > { |
} |
}; |
+template <typename T> |
+struct UnwrapTraits<PassedWrapper<T> > { |
+ typedef T ForwardType; |
+ static T Unwrap(PassedWrapper<T>& o) { |
+ return o.Pass(); |
+ } |
+}; |
+ |
// Utility for handling different refcounting semantics in the Bind() |
// function. |
-template <bool, typename T> |
+template <bool is_method, typename T> |
struct MaybeRefcount; |
template <typename T> |
@@ -348,21 +437,15 @@ struct MaybeRefcount<false, T[n]> { |
}; |
template <typename T> |
-struct MaybeRefcount<true, T*> { |
- static void AddRef(T* o) { o->AddRef(); } |
- static void Release(T* o) { o->Release(); } |
-}; |
- |
-template <typename T> |
-struct MaybeRefcount<true, UnretainedWrapper<T> > { |
- static void AddRef(const UnretainedWrapper<T>&) {} |
- static void Release(const UnretainedWrapper<T>&) {} |
+struct MaybeRefcount<true, T> { |
+ static void AddRef(const T&) {} |
+ static void Release(const T&) {} |
}; |
template <typename T> |
-struct MaybeRefcount<true, OwnedWrapper<T> > { |
- static void AddRef(const OwnedWrapper<T>&) {} |
- static void Release(const OwnedWrapper<T>&) {} |
+struct MaybeRefcount<true, T*> { |
+ static void AddRef(T* o) { o->AddRef(); } |
+ static void Release(T* o) { o->Release(); } |
}; |
// No need to additionally AddRef() and Release() since we are storing a |
@@ -379,19 +462,13 @@ struct MaybeRefcount<true, const T*> { |
static void Release(const T* o) { o->Release(); } |
}; |
-template <typename T> |
-struct MaybeRefcount<true, WeakPtr<T> > { |
- static void AddRef(const WeakPtr<T>&) {} |
- static void Release(const WeakPtr<T>&) {} |
-}; |
- |
template <typename R> |
void VoidReturnAdapter(Callback<R(void)> callback) { |
callback.Run(); |
} |
// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a |
-// method. It is unsed internally by Bind() to select the correct |
+// method. It is used internally by Bind() to select the correct |
// InvokeHelper that will no-op itself in the event the WeakPtr<> for |
// the target object is invalidated. |
// |
@@ -422,6 +499,20 @@ static inline internal::OwnedWrapper<T> Owned(T* o) { |
return internal::OwnedWrapper<T>(o); |
} |
+// We offer 2 syntaxes for calling Passed(). The first takes a temporary and |
+// is best suited for use with the return value of a function. The second |
+// takes a pointer to the scoper and is just syntactic sugar to avoid having |
+// to write Passed(scoper.Pass()). |
+template <typename T> |
+static inline internal::PassedWrapper<T> Passed(T scoper) { |
+ return internal::PassedWrapper<T>(scoper.Pass()); |
+} |
+template <typename T> |
+static inline internal::PassedWrapper<T> Passed(T* scoper) { |
+ return internal::PassedWrapper<T>(scoper->Pass()); |
+} |
+ |
+// -- DEPRECATED -- Use IgnoreResult instead. |
template <typename R> |
static inline Closure IgnoreReturn(Callback<R(void)> callback) { |
return Bind(&internal::VoidReturnAdapter<R>, callback); |
@@ -438,7 +529,6 @@ IgnoreResult(const Callback<T>& data) { |
return internal::IgnoreResultHelper<Callback<T> >(data); |
} |
- |
} // namespace base |
#endif // BASE_BIND_HELPERS_H_ |