diff options
-rw-r--r-- | base/bind_helpers.h | 152 | ||||
-rw-r--r-- | base/bind_internal.h | 267 | ||||
-rw-r--r-- | base/bind_internal.h.pump | 15 | ||||
-rw-r--r-- | base/bind_unittest.cc | 67 | ||||
-rw-r--r-- | base/callback.h | 56 | ||||
-rw-r--r-- | base/callback.h.pump | 2 | ||||
-rw-r--r-- | base/callback_internal.h | 59 | ||||
-rw-r--r-- | base/memory/scoped_ptr.h | 93 | ||||
-rw-r--r-- | base/memory/scoped_ptr_unittest.cc | 92 |
9 files changed, 640 insertions, 163 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h index 6e0f8fe..df8cf82 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_ diff --git a/base/bind_internal.h b/base/bind_internal.h index ccd7ab2..50ffaa5 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -76,7 +76,6 @@ namespace internal { // into the Bind() system, doing most of the type resolution. // There are ARITY BindState types. - // RunnableAdapter<> // // The RunnableAdapter<> templates provide a uniform interface for invoking @@ -167,7 +166,7 @@ class RunnableAdapter<R(*)(A1)> { } R Run(typename CallbackParamTraits<A1>::ForwardType a1) { - return function_(a1); + return function_(CallbackForward(a1)); } private: @@ -186,7 +185,7 @@ class RunnableAdapter<R(T::*)(A1)> { } R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1) { - return (object->*method_)(a1); + return (object->*method_)(CallbackForward(a1)); } private: @@ -205,7 +204,7 @@ class RunnableAdapter<R(T::*)(A1) const> { } R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1) { - return (object->*method_)(a1); + return (object->*method_)(CallbackForward(a1)); } private: @@ -224,7 +223,7 @@ class RunnableAdapter<R(*)(A1, A2)> { R Run(typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2) { - return function_(a1, a2); + return function_(CallbackForward(a1), CallbackForward(a2)); } private: @@ -244,7 +243,7 @@ class RunnableAdapter<R(T::*)(A1, A2)> { R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2) { - return (object->*method_)(a1, a2); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); } private: @@ -264,7 +263,7 @@ class RunnableAdapter<R(T::*)(A1, A2) const> { R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2) { - return (object->*method_)(a1, a2); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); } private: @@ -284,7 +283,8 @@ class RunnableAdapter<R(*)(A1, A2, A3)> { R Run(typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3) { - return function_(a1, a2, a3); + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); } private: @@ -305,7 +305,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3)> { R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3) { - return (object->*method_)(a1, a2, a3); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); } private: @@ -326,7 +327,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3) const> { R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1, typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3) { - return (object->*method_)(a1, a2, a3); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); } private: @@ -347,7 +349,8 @@ class RunnableAdapter<R(*)(A1, A2, A3, A4)> { typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4) { - return function_(a1, a2, a3, a4); + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); } private: @@ -370,7 +373,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4)> { typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4) { - return (object->*method_)(a1, a2, a3, a4); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); } private: @@ -393,7 +397,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4) const> { typename CallbackParamTraits<A2>::ForwardType a2, typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4) { - return (object->*method_)(a1, a2, a3, a4); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); } private: @@ -416,7 +421,8 @@ class RunnableAdapter<R(*)(A1, A2, A3, A4, A5)> { typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5) { - return function_(a1, a2, a3, a4, a5); + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); } private: @@ -440,7 +446,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5)> { typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5) { - return (object->*method_)(a1, a2, a3, a4, a5); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); } private: @@ -464,7 +471,8 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5) const> { typename CallbackParamTraits<A3>::ForwardType a3, typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5) { - return (object->*method_)(a1, a2, a3, a4, a5); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); } private: @@ -488,7 +496,9 @@ class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6)> { typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6) { - return function_(a1, a2, a3, a4, a5, a6); + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); } private: @@ -513,7 +523,9 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6)> { typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6) { - return (object->*method_)(a1, a2, a3, a4, a5, a6); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); } private: @@ -538,7 +550,9 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6) const> { typename CallbackParamTraits<A4>::ForwardType a4, typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6) { - return (object->*method_)(a1, a2, a3, a4, a5, a6); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); } private: @@ -563,7 +577,9 @@ class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6, A7)> { typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6, typename CallbackParamTraits<A7>::ForwardType a7) { - return function_(a1, a2, a3, a4, a5, a6, a7); + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); } private: @@ -589,7 +605,9 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7)> { typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6, typename CallbackParamTraits<A7>::ForwardType a7) { - return (object->*method_)(a1, a2, a3, a4, a5, a6, a7); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); } private: @@ -615,7 +633,9 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7) const> { typename CallbackParamTraits<A5>::ForwardType a5, typename CallbackParamTraits<A6>::ForwardType a6, typename CallbackParamTraits<A7>::ForwardType a7) { - return (object->*method_)(a1, a2, a3, a4, a5, a6, a7); + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); } private: @@ -837,7 +857,7 @@ template <typename ReturnType, typename Runnable,typename A1> struct InvokeHelper<false, ReturnType, Runnable, void(A1)> { static ReturnType MakeItSo(Runnable runnable, A1 a1) { - return runnable.Run(a1); + return runnable.Run(CallbackForward(a1)); } }; @@ -845,7 +865,7 @@ template <typename Runnable,typename A1> struct InvokeHelper<false, void, Runnable, void(A1)> { static void MakeItSo(Runnable runnable, A1 a1) { - runnable.Run(a1); + runnable.Run(CallbackForward(a1)); } }; @@ -857,7 +877,7 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1); + runnable.Run(CallbackForward(a1)); } }; @@ -865,7 +885,7 @@ template <typename ReturnType, typename Runnable,typename A1, typename A2> struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) { - return runnable.Run(a1, a2); + return runnable.Run(CallbackForward(a1), CallbackForward(a2)); } }; @@ -873,7 +893,7 @@ template <typename Runnable,typename A1, typename A2> struct InvokeHelper<false, void, Runnable, void(A1, A2)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2) { - runnable.Run(a1, a2); + runnable.Run(CallbackForward(a1), CallbackForward(a2)); } }; @@ -885,7 +905,7 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2); + runnable.Run(CallbackForward(a1), CallbackForward(a2)); } }; @@ -894,7 +914,8 @@ template <typename ReturnType, typename Runnable,typename A1, typename A2, struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { - return runnable.Run(a1, a2, a3); + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); } }; @@ -902,7 +923,7 @@ template <typename Runnable,typename A1, typename A2, typename A3> struct InvokeHelper<false, void, Runnable, void(A1, A2, A3)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { - runnable.Run(a1, a2, a3); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3)); } }; @@ -914,7 +935,7 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2, a3); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3)); } }; @@ -923,7 +944,8 @@ template <typename ReturnType, typename Runnable,typename A1, typename A2, struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { - return runnable.Run(a1, a2, a3, a4); + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); } }; @@ -931,7 +953,8 @@ template <typename Runnable,typename A1, typename A2, typename A3, typename A4> struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { - runnable.Run(a1, a2, a3, a4); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); } }; @@ -943,7 +966,8 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2, a3, a4); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); } }; @@ -953,7 +977,8 @@ struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4, A5)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return runnable.Run(a1, a2, a3, a4, a5); + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); } }; @@ -962,7 +987,8 @@ template <typename Runnable,typename A1, typename A2, typename A3, typename A4, struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - runnable.Run(a1, a2, a3, a4, a5); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); } }; @@ -975,7 +1001,8 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2, a3, a4, a5); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); } }; @@ -985,7 +1012,9 @@ struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4, A5, A6)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return runnable.Run(a1, a2, a3, a4, a5, a6); + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); } }; @@ -995,7 +1024,8 @@ struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5, A6)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - runnable.Run(a1, a2, a3, a4, a5, a6); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); } }; @@ -1009,7 +1039,8 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2, a3, a4, a5, a6); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); } }; @@ -1019,7 +1050,9 @@ struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4, A5, A6, A7)> { static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return runnable.Run(a1, a2, a3, a4, a5, a6, a7); + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); } }; @@ -1029,7 +1062,9 @@ struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5, A6, A7)> { static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - runnable.Run(a1, a2, a3, a4, a5, a6, a7); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); } }; @@ -1043,7 +1078,9 @@ struct InvokeHelper<true, void, Runnable, return; } - runnable.Run(a1, a2, a3, a4, a5, a6, a7); + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); } }; @@ -1106,7 +1143,7 @@ struct Invoker<0, StorageType, R(X1)> { return InvokeHelper<StorageType::IsWeakCall::value, R, typename StorageType::RunnableType, void(typename CallbackParamTraits<X1>::ForwardType x1)> - ::MakeItSo(storage->runnable_, x1); + ::MakeItSo(storage->runnable_, CallbackForward(x1)); } }; @@ -1130,7 +1167,7 @@ struct Invoker<1, StorageType, R(X1)> { return InvokeHelper<StorageType::IsWeakCall::value, R, typename StorageType::RunnableType, void(typename Bound1UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1); + ::MakeItSo(storage->runnable_, CallbackForward(x1)); } }; @@ -1156,7 +1193,8 @@ struct Invoker<0, StorageType, R(X1, X2)> { typename StorageType::RunnableType, void(typename CallbackParamTraits<X1>::ForwardType x1, typename CallbackParamTraits<X2>::ForwardType x2)> - ::MakeItSo(storage->runnable_, x1, x2); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); } }; @@ -1183,7 +1221,8 @@ struct Invoker<1, StorageType, R(X1, X2)> { typename StorageType::RunnableType, void(typename Bound1UnwrapTraits::ForwardType, typename CallbackParamTraits<X2>::ForwardType x2)> - ::MakeItSo(storage->runnable_, x1, x2); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); } }; @@ -1211,7 +1250,8 @@ struct Invoker<2, StorageType, R(X1, X2)> { typename StorageType::RunnableType, void(typename Bound1UnwrapTraits::ForwardType, typename Bound2UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); } }; @@ -1241,7 +1281,8 @@ struct Invoker<0, StorageType, R(X1, X2, X3)> { void(typename CallbackParamTraits<X1>::ForwardType x1, typename CallbackParamTraits<X2>::ForwardType x2, typename CallbackParamTraits<X3>::ForwardType x3)> - ::MakeItSo(storage->runnable_, x1, x2, x3); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); } }; @@ -1272,7 +1313,8 @@ struct Invoker<1, StorageType, R(X1, X2, X3)> { void(typename Bound1UnwrapTraits::ForwardType, typename CallbackParamTraits<X2>::ForwardType x2, typename CallbackParamTraits<X3>::ForwardType x3)> - ::MakeItSo(storage->runnable_, x1, x2, x3); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); } }; @@ -1304,7 +1346,8 @@ struct Invoker<2, StorageType, R(X1, X2, X3)> { void(typename Bound1UnwrapTraits::ForwardType, typename Bound2UnwrapTraits::ForwardType, typename CallbackParamTraits<X3>::ForwardType x3)> - ::MakeItSo(storage->runnable_, x1, x2, x3); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); } }; @@ -1337,7 +1380,8 @@ struct Invoker<3, StorageType, R(X1, X2, X3)> { void(typename Bound1UnwrapTraits::ForwardType, typename Bound2UnwrapTraits::ForwardType, typename Bound3UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2, x3); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); } }; @@ -1370,7 +1414,9 @@ struct Invoker<0, StorageType, R(X1, X2, X3, X4)> { typename CallbackParamTraits<X2>::ForwardType x2, typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); } }; @@ -1404,7 +1450,9 @@ struct Invoker<1, StorageType, R(X1, X2, X3, X4)> { typename CallbackParamTraits<X2>::ForwardType x2, typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); } }; @@ -1439,7 +1487,9 @@ struct Invoker<2, StorageType, R(X1, X2, X3, X4)> { typename Bound2UnwrapTraits::ForwardType, typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); } }; @@ -1475,7 +1525,9 @@ struct Invoker<3, StorageType, R(X1, X2, X3, X4)> { typename Bound2UnwrapTraits::ForwardType, typename Bound3UnwrapTraits::ForwardType, typename CallbackParamTraits<X4>::ForwardType x4)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); } }; @@ -1512,7 +1564,9 @@ struct Invoker<4, StorageType, R(X1, X2, X3, X4)> { typename Bound2UnwrapTraits::ForwardType, typename Bound3UnwrapTraits::ForwardType, typename Bound4UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); } }; @@ -1548,7 +1602,9 @@ struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> { typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1585,7 +1641,9 @@ struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> { typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1623,7 +1681,9 @@ struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> { typename CallbackParamTraits<X3>::ForwardType x3, typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1662,7 +1722,9 @@ struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> { typename Bound3UnwrapTraits::ForwardType, typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1702,7 +1764,9 @@ struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> { typename Bound3UnwrapTraits::ForwardType, typename Bound4UnwrapTraits::ForwardType, typename CallbackParamTraits<X5>::ForwardType x5)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1743,7 +1807,9 @@ struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> { typename Bound3UnwrapTraits::ForwardType, typename Bound4UnwrapTraits::ForwardType, typename Bound5UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); } }; @@ -1782,7 +1848,10 @@ struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -1822,7 +1891,10 @@ struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -1863,7 +1935,10 @@ struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -1905,7 +1980,10 @@ struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename CallbackParamTraits<X4>::ForwardType x4, typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -1948,7 +2026,10 @@ struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename Bound4UnwrapTraits::ForwardType, typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -1992,7 +2073,10 @@ struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename Bound4UnwrapTraits::ForwardType, typename Bound5UnwrapTraits::ForwardType, typename CallbackParamTraits<X6>::ForwardType x6)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -2037,7 +2121,10 @@ struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> { typename Bound4UnwrapTraits::ForwardType, typename Bound5UnwrapTraits::ForwardType, typename Bound6UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); } }; @@ -2079,7 +2166,10 @@ struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2122,7 +2212,10 @@ struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2166,7 +2259,10 @@ struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2211,7 +2307,10 @@ struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2257,7 +2356,10 @@ struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename CallbackParamTraits<X5>::ForwardType x5, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2304,7 +2406,10 @@ struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename Bound5UnwrapTraits::ForwardType, typename CallbackParamTraits<X6>::ForwardType x6, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2352,7 +2457,10 @@ struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename Bound5UnwrapTraits::ForwardType, typename Bound6UnwrapTraits::ForwardType, typename CallbackParamTraits<X7>::ForwardType x7)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; @@ -2401,7 +2509,10 @@ struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { typename Bound5UnwrapTraits::ForwardType, typename Bound6UnwrapTraits::ForwardType, typename Bound7UnwrapTraits::ForwardType)> - ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); } }; diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 53dcbd3..7fd63d8 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -82,7 +82,6 @@ namespace internal { // into the Bind() system, doing most of the type resolution. // There are ARITY BindState types. - // RunnableAdapter<> // // The RunnableAdapter<> templates provide a uniform interface for invoking @@ -121,7 +120,7 @@ class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> { } R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { - return function_($for ARG , [[a$(ARG)]]); + return function_($for ARG , [[CallbackForward(a$(ARG))]]); } private: @@ -143,7 +142,7 @@ $if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); R Run(T* object[[]] $if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { - return (object->*method_)($for ARG , [[a$(ARG)]]); + return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]); } private: @@ -165,7 +164,7 @@ $if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); R Run(const T* object[[]] $if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { - return (object->*method_)($for ARG , [[a$(ARG)]]); + return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]); } private: @@ -291,7 +290,7 @@ struct InvokeHelper<false, ReturnType, Runnable, void($for ARG , [[A$(ARG)]])> { static ReturnType MakeItSo(Runnable runnable[[]] $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { - return runnable.Run($for ARG , [[a$(ARG)]]); + return runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]); } }; @@ -301,7 +300,7 @@ struct InvokeHelper<false, void, Runnable, void($for ARG , [[A$(ARG)]])> { static void MakeItSo(Runnable runnable[[]] $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { - runnable.Run($for ARG , [[a$(ARG)]]); + runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]); } }; @@ -316,7 +315,7 @@ $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { return; } - runnable.Run($for ARG , [[a$(ARG)]]); + runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]); } }; @@ -404,7 +403,7 @@ typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG) ]] )> ::MakeItSo(storage->runnable_ -$if ARITY > 0[[, ]] $for ARG , [[x$(ARG)]]); +$if ARITY > 0[[, ]] $for ARG , [[CallbackForward(x$(ARG))]]); } }; diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 654a277..d150362 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -5,6 +5,9 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -102,7 +105,7 @@ class CopyCounter { (*copies_)++; } - // Probing for copies from coerscion. + // Probing for copies from coercion. CopyCounter(const DerivedCopyCounter& other) : copies_(other.copies_), assigns_(other.assigns_) { @@ -149,6 +152,11 @@ class DeleteCounter { int* deletes_; }; +template <typename T> +T PassThru(T scoper) { + return scoper.Pass(); +} + // Some test functions that we can Bind to. template <typename T> T PolymorphicIdentity(T t) { @@ -641,8 +649,8 @@ TEST_F(BindTest, Owned) { // return the same value. Callback<DeleteCounter*(void)> no_capture_cb = Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter)); - EXPECT_EQ(counter, no_capture_cb.Run()); - EXPECT_EQ(counter, no_capture_cb.Run()); + ASSERT_EQ(counter, no_capture_cb.Run()); + ASSERT_EQ(counter, no_capture_cb.Run()); EXPECT_EQ(0, deletes); no_capture_cb.Reset(); // This should trigger a delete. EXPECT_EQ(1, deletes); @@ -657,11 +665,60 @@ TEST_F(BindTest, Owned) { EXPECT_EQ(1, deletes); } +// Passed() wrapper support. +// - Passed() can be constructed from a pointer to scoper. +// - Passed() can be constructed from a scoper rvalue. +// - Using Passed() gives Callback Ownership. +// - Ownership is transferred from Callback to callee on the first Run(). +// - Callback supports unbound arguments. +TEST_F(BindTest, ScopedPtr) { + int deletes = 0; + + // Tests the Passed() function's support for pointers. + scoped_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes)); + Callback<scoped_ptr<DeleteCounter>(void)> unused_callback = + Bind(&PassThru<scoped_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<scoped_ptr<DeleteCounter>(void)> callback = + Bind(&PassThru<scoped_ptr<DeleteCounter> >, + Passed(scoped_ptr<DeleteCounter>(counter))); + EXPECT_FALSE(ptr.get()); + EXPECT_EQ(0, deletes); + + // Check that ownership can be transferred back out. + scoped_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<scoped_ptr<DeleteCounter>(scoped_ptr<DeleteCounter>)> cb_unbound = + Bind(&PassThru<scoped_ptr<DeleteCounter> >); + ptr.reset(new DeleteCounter(&deletes)); + cb_unbound.Run(ptr.Pass()); +} + // Argument Copy-constructor usage for non-reference parameters. // - Bound arguments are only copied once. // - Forwarded arguments are only copied once. -// - Forwarded arguments with coerscions are only copied twice (once for the -// coerscion, and one for the final dispatch). +// - Forwarded arguments with coercions are only copied twice (once for the +// coercion, and one for the final dispatch). TEST_F(BindTest, ArgumentCopies) { int copies = 0; int assigns = 0; diff --git a/base/callback.h b/base/callback.h index 09c3ef7..001dd07 100644 --- a/base/callback.h +++ b/base/callback.h @@ -312,7 +312,7 @@ class Callback<R(A1)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1); + return f(bind_state_.get(), internal::CallbackForward(a1)); } private: @@ -355,8 +355,8 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2)); } private: @@ -401,9 +401,9 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2, - a3); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3)); } private: @@ -450,10 +450,10 @@ class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2, - a3, - a4); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4)); } private: @@ -503,11 +503,11 @@ class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2, - a3, - a4, - a5); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5)); } private: @@ -559,12 +559,12 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2, - a3, - a4, - a5, - a6); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6)); } private: @@ -618,13 +618,13 @@ class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(bind_state_.get(), a1, - a2, - a3, - a4, - a5, - a6, - a7); + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6), + internal::CallbackForward(a7)); } private: diff --git a/base/callback.h.pump b/base/callback.h.pump index 7647389..82660f3 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -291,7 +291,7 @@ class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase { return f(bind_state_.get()[[]] $if ARITY != 0 [[, ]] $for ARG , - [[a$(ARG)]]); + [[internal::CallbackForward(a$(ARG))]]); } private: diff --git a/base/callback_internal.h b/base/callback_internal.h index 81c87c0..b734568 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -13,6 +13,7 @@ #include "base/base_export.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" namespace base { namespace internal { @@ -130,6 +131,64 @@ struct CallbackParamTraits<T[]> { typedef const T* StorageType; }; +// Parameter traits for movable-but-not-copyable scopers. +// +// Callback<>/Bind() understands movable-but-not-copyable semantics where +// the type cannot be copied but can still have its state destructively +// transferred (aka. moved) to another instance of the same type by calling a +// helper function. When used with Bind(), this signifies transferal of the +// object's state to the target function. +// +// For these types, the ForwardType must not be a const reference, or a +// reference. A const reference is inappropriate, and would break const +// correctness, because we are implementing a destructive move. A non-const +// reference cannot be used with temporaries which means the result of a +// function or a cast would not be usable with Callback<> or Bind(). +// +// TODO(ajwong): We might be able to use SFINAE to search for the existence of +// a Pass() function in the type and avoid the whitelist in CallbackParamTraits +// and CallbackForward. +template <typename T> +struct CallbackParamTraits<scoped_ptr<T> > { + typedef scoped_ptr<T> ForwardType; + typedef scoped_ptr<T> StorageType; +}; + +template <typename T> +struct CallbackParamTraits<scoped_array<T> > { + typedef scoped_array<T> ForwardType; + typedef scoped_array<T> StorageType; +}; + +template <typename T> +struct CallbackParamTraits<scoped_ptr_malloc<T> > { + typedef scoped_ptr_malloc<T> ForwardType; + typedef scoped_ptr_malloc<T> StorageType; +}; + +// CallbackForward() is a very limited simulation of C++11's std::forward() +// used by the Callback/Bind system for a set of movable-but-not-copyable +// types. It is needed because forwarding a movable-but-not-copyable +// argument to another function requires us to invoke the proper move +// operator to create a rvalue version of the type. The supported types are +// whitelisted below as overloads of the CallbackForward() function. The +// default template compiles out to be a no-op. +// +// 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. +template <typename T> +T& CallbackForward(T& t) { return t; } + +template <typename T> +scoped_ptr<T> CallbackForward(scoped_ptr<T>& p) { return p.Pass(); } + +template <typename T> +scoped_ptr<T> CallbackForward(scoped_array<T>& p) { return p.Pass(); } + +template <typename T> +scoped_ptr<T> CallbackForward(scoped_ptr_malloc<T>& p) { return p.Pass(); } + } // namespace internal } // namespace base diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h index 5ac6846..2d69a9d 100644 --- a/base/memory/scoped_ptr.h +++ b/base/memory/scoped_ptr.h @@ -32,6 +32,41 @@ // foo.get()->Method(); // Foo::Method on the 0th element. // foo[10].Method(); // Foo::Method on the 10th element. // } +// +// These scopers also implement part of the functionality of C++11 unique_ptr +// in that they are "movable but not copyable." You can use the scopers in +// the parameter and return types of functions to signify ownership transfer +// in to and out of a function. When calling a function that has a scoper +// as the argument type, it must be called with the result of an analogous +// scoper's Pass() function or another function that generates a temporary; +// passing by copy will NOT work. Here is an example using scoped_ptr: +// +// void TakesOwnership(scoped_ptr<Foo> arg) { +// // Do something with arg +// } +// scoped_ptr<Foo> CreateFoo() { +// // No need for calling Pass() because we are constructing a temporary +// // for the return value. +// return scoped_ptr<Foo>(new Foo("new")); +// } +// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { +// return arg.Pass(); +// } +// +// { +// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay)" +// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). +// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. +// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. +// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. +// } +// +// Notice that if you do not call Pass() when returning from PassThru(), or +// when invoking TakesOwnership(), the code will not compile because scopers +// are not copyable; they only implement move semantics which require calling +// the Pass() function to signify a destructive transfer of state. CreateFoo() +// is different though because we are constructing a temporary on the return +// line and thus can avoid needing to call Pass(). #ifndef BASE_MEMORY_SCOPED_PTR_H_ #define BASE_MEMORY_SCOPED_PTR_H_ @@ -47,12 +82,35 @@ #include "base/compiler_specific.h" +// Macro with the boilerplate C++03 move emulation for a class. +// +// In C++11, this is done via rvalue references. Here, we use C++03 move +// emulation to fake an rvalue reference. For a more thorough explanation +// of the technique, see: +// +// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor +// +#define CPP_03_MOVE_EMULATION(scoper, field) \ + private: \ + struct RValue { \ + explicit RValue(scoper& obj) : obj_(obj) {} \ + scoper& obj_; \ + }; \ + public: \ + operator RValue() { return RValue(*this); } \ + scoper(RValue proxy) : field(proxy.obj_.release()) { } \ + scoper& operator=(RValue proxy) { \ + swap(proxy.obj_); \ + return *this; \ + } \ + scoper Pass() { return scoper(RValue(*this)); } + // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> // automatically deletes the pointer it holds (if any). // That is, scoped_ptr<T> owns the T object that it points to. // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. // Also like T*, scoped_ptr<T> is thread-compatible, and once you -// dereference it, you get the threadsafety guarantees of T. +// dereference it, you get the thread safety guarantees of T. // // The size of a scoped_ptr is small: // sizeof(scoped_ptr<C>) == sizeof(C*) @@ -122,6 +180,8 @@ class scoped_ptr { return retVal; } + CPP_03_MOVE_EMULATION(scoped_ptr, ptr_); + private: C* ptr_; @@ -131,9 +191,10 @@ class scoped_ptr { template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; - // Disallow evil constructors - scoped_ptr(const scoped_ptr&); - void operator=(const scoped_ptr&); + // Disallow evil constructors. Note that MUST NOT take a const& because we + // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. + scoped_ptr(scoped_ptr&); + void operator=(scoped_ptr&); }; // Free functions @@ -158,7 +219,7 @@ bool operator!=(C* p1, const scoped_ptr<C>& p2) { // As with scoped_ptr<C>, a scoped_array<C> either points to an object // or is NULL. A scoped_array<C> owns the object that it points to. // scoped_array<T> is thread-compatible, and once you index into it, -// the returned objects have only the threadsafety guarantees of T. +// the returned objects have only the thread safety guarantees of T. // // Size: sizeof(scoped_array<C>) == sizeof(C*) template <class C> @@ -168,7 +229,7 @@ class scoped_array { // The element type typedef C element_type; - // Constructor. Defaults to intializing with NULL. + // Constructor. Defaults to initializing with NULL. // There is no way to create an uninitialized scoped_array. // The input parameter must be allocated with new []. explicit scoped_array(C* p = NULL) : array_(p) { } @@ -229,6 +290,8 @@ class scoped_array { return retVal; } + CPP_03_MOVE_EMULATION(scoped_array, array_); + private: C* array_; @@ -236,9 +299,10 @@ class scoped_array { template <class C2> bool operator==(scoped_array<C2> const& p2) const; template <class C2> bool operator!=(scoped_array<C2> const& p2) const; - // Disallow evil constructors - scoped_array(const scoped_array&); - void operator=(const scoped_array&); + // Disallow evil constructors. Note that MUST NOT take a const& because we + // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. + scoped_array(scoped_array&); + void operator=(scoped_array&); }; // Free functions @@ -347,6 +411,8 @@ class scoped_ptr_malloc { return tmp; } + CPP_03_MOVE_EMULATION(scoped_ptr_malloc, ptr_); + private: C* ptr_; @@ -356,11 +422,14 @@ class scoped_ptr_malloc { template <class C2, class GP> bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; - // Disallow evil constructors - scoped_ptr_malloc(const scoped_ptr_malloc&); - void operator=(const scoped_ptr_malloc&); + // Disallow evil constructors. Note that MUST NOT take a const& because we + // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. + scoped_ptr_malloc(scoped_ptr_malloc&); + void operator=(scoped_ptr_malloc&); }; +#undef CPP_03_MOVE_EMULATION + template<class C, class FP> inline void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { a.swap(b); diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc index 7519051..9a37cbf 100644 --- a/base/memory/scoped_ptr_unittest.cc +++ b/base/memory/scoped_ptr_unittest.cc @@ -23,6 +23,19 @@ class ConDecLogger { DISALLOW_COPY_AND_ASSIGN(ConDecLogger); }; +scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { + return logger.Pass(); +} + +void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { +} + +// Do not delete this function! It's existence is to test that you can +// return a temporarily constructed version of the scoper. +scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) { + return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed)); +} + } // namespace TEST(ScopedPtrTest, ScopedPtr) { @@ -166,4 +179,83 @@ TEST(ScopedPtrTest, ScopedArray) { EXPECT_EQ(0, constructed); } +TEST(ScopedPtrTest, PassBehavior) { + int constructed = 0; + { + ConDecLogger* logger = new ConDecLogger(&constructed); + scoped_ptr<ConDecLogger> scoper(logger); + EXPECT_EQ(1, constructed); + + // Test Pass() with constructor; + scoped_ptr<ConDecLogger> scoper2(scoper.Pass()); + EXPECT_EQ(1, constructed); + + // Test Pass() with assignment; + scoped_ptr<ConDecLogger> scoper3; + scoper3 = scoper2.Pass(); + EXPECT_EQ(1, constructed); + EXPECT_FALSE(scoper.get()); + EXPECT_FALSE(scoper2.get()); + EXPECT_TRUE(scoper3.get()); + } + + // Test uncaught Pass() does not leak. + { + ConDecLogger* logger = new ConDecLogger(&constructed); + scoped_ptr<ConDecLogger> scoper(logger); + EXPECT_EQ(1, constructed); + + // Should auto-destruct logger by end of scope. + scoper.Pass(); + EXPECT_FALSE(scoper.get()); + } + EXPECT_EQ(0, constructed); + + // Test that passing to function which does nothing does not leak. + { + ConDecLogger* logger = new ConDecLogger(&constructed); + scoped_ptr<ConDecLogger> scoper(logger); + EXPECT_EQ(1, constructed); + + // Should auto-destruct logger by end of scope. + GrabAndDrop(scoper.Pass()); + EXPECT_FALSE(scoper.get()); + } + EXPECT_EQ(0, constructed); +} + +TEST(ScopedPtrTest, ReturnTypeBehavior) { + int constructed = 0; + + // Test that we can return a scoped_ptr. + { + ConDecLogger* logger = new ConDecLogger(&constructed); + scoped_ptr<ConDecLogger> scoper(logger); + EXPECT_EQ(1, constructed); + + PassThru(scoper.Pass()); + EXPECT_FALSE(scoper.get()); + } + EXPECT_EQ(0, constructed); + + // Test uncaught return type not leak. + { + ConDecLogger* logger = new ConDecLogger(&constructed); + scoped_ptr<ConDecLogger> scoper(logger); + EXPECT_EQ(1, constructed); + + // Should auto-destruct logger by end of scope. + PassThru(scoper.Pass()); + EXPECT_FALSE(scoper.get()); + } + EXPECT_EQ(0, constructed); + + // Call TestReturnOfType() so the compiler doesn't warn for an unused + // function. + { + TestReturnOfType(&constructed); + } + EXPECT_EQ(0, constructed); +} + // TODO scoped_ptr_malloc |