Chromium Code Reviews| Index: base/bind_helpers.h |
| diff --git a/base/bind_helpers.h b/base/bind_helpers.h |
| index 6e0f8fe72742a06f7875d5f73a4b9e0ec97f6c45..151e9816fd04a7dbcf710bc27cf36dffb43602c8 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 transfering moveable-but-not-copyable types (eg. scoped_ptr) |
|
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfering/transferring/
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
|
| +// 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 |
| +// transfered ownership to the target function. |
|
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfered/transferred/
awong
2011/12/08 21:04:10
Done.
|
| +// |
| // 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 longers owns Foo() and, if reset, would not delete Foo(). |
| +// cb.Run(); // Foo() is now transfered to |arg| and deleted. |
|
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfered/transferred/
awong
2011/12/08 21:04:10
Done.
|
| +// cb.Run(); // This CHECK()s since Foo() already been used once. |
|
willchan no longer on Chromium
2011/12/07 16:24:34
Is there actually a CHECK somewhere? Or does it SI
awong
2011/12/08 21:04:10
Yep. There's a distinction between initializing P
|
| +// |
| +// Passed() is particularly useful with PostTask() when you are transfering |
| +// 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_ |
| @@ -90,6 +132,7 @@ |
| #include "base/basictypes.h" |
| #include "base/bind.h" |
| #include "base/callback.h" |
| +#include "base/memory/scoped_ptr.h" |
|
willchan no longer on Chromium
2011/12/07 16:24:34
This isn't necessary is it?
awong
2011/12/08 21:04:10
Not anymore. Removed.
|
| #include "base/memory/weak_ptr.h" |
| #include "base/template_util.h" |
| @@ -287,6 +330,38 @@ 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 moveable-but-not-copyable |
|
willchan no longer on Chromium
2011/12/07 16:24:34
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
|
| +// types; doing a destructive "move" of the type into Bind() would violate |
| +// the const correctness. |
| +// |
| +// This connundrum 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 moveable-but-not-copyable types. Thus we introduce a wrapper type |
|
willchan no longer on Chromium
2011/12/07 16:24:34
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
|
| +// that is copyable to transmit the get the correct type information down into |
|
willchan no longer on Chromium
2011/12/07 16:24:34
transmit the get the correct type?
awong
2011/12/08 21:04:10
Done.
|
| +// BindState<>. Ignoring const in this type makes sense because it is only |
| +// created when we are explicitly trying to do a destructive move. |
| +template <typename T> |
| +class PassedWrapper { |
| + public: |
| + explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} |
|
willchan no longer on Chromium
2011/12/07 16:24:34
Does this work for anything with Pass() defined? D
awong
2011/12/08 21:04:10
It works for anything with Pass(). I think this i
|
| + 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 +405,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 +431,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,12 +456,6 @@ 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(); |
| @@ -422,6 +493,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 +523,6 @@ IgnoreResult(const Callback<T>& data) { |
| return internal::IgnoreResultHelper<Callback<T> >(data); |
| } |
| - |
| } // namespace base |
| #endif // BASE_BIND_HELPERS_H_ |