| 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_
|
|
|