diff options
Diffstat (limited to 'third_party/chromium/base/bind_helpers.h')
-rw-r--r-- | third_party/chromium/base/bind_helpers.h | 268 |
1 files changed, 86 insertions, 182 deletions
diff --git a/third_party/chromium/base/bind_helpers.h b/third_party/chromium/base/bind_helpers.h index 5a4524a..93d02e3 100644 --- a/third_party/chromium/base/bind_helpers.h +++ b/third_party/chromium/base/bind_helpers.h @@ -28,6 +28,9 @@ // argument will CHECK() because the first invocation would have already // transferred ownership to the target function. // +// RetainedRef() accepts a ref counted object and retains a reference to it. +// When the callback is called, the object is passed as a raw pointer. +// // ConstRef() allows binding a constant reference to an argument rather // than a copy. // @@ -71,6 +74,19 @@ // Without Owned(), someone would have to know to delete |pn| when the last // reference to the Callback is deleted. // +// EXAMPLE OF RetainedRef(): +// +// void foo(RefCountedBytes* bytes) {} +// +// scoped_refptr<RefCountedBytes> bytes = ...; +// Closure callback = Bind(&foo, base::RetainedRef(bytes)); +// callback.Run(); +// +// Without RetainedRef, the scoped_refptr would try to implicitly convert to +// a raw pointer and fail compilation: +// +// Closure callback = Bind(&foo, bytes); // ERROR! +// // // EXAMPLE OF ConstRef(): // @@ -105,10 +121,11 @@ // // EXAMPLE OF Passed(): // -// void TakesOwnership(scoped_ptr<Foo> arg) { } -// scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } +// void TakesOwnership(std::unique_ptr<Foo> arg) { } +// std::unique_ptr<Foo> CreateFoo() { return std::unique_ptr<Foo>(new Foo()); +// } // -// scoped_ptr<Foo> f(new Foo()); +// std::unique_ptr<Foo> f(new Foo()); // // // |cb| is given ownership of Foo(). |f| is now NULL. // // You can use std::move(f) in place of &f, but it's more verbose. @@ -145,156 +162,19 @@ #include <stddef.h> -#include <map> -#include <memory> #include <type_traits> #include <utility> -#include <vector> #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" namespace base { -namespace internal { - -// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T -// for the existence of AddRef() and Release() functions of the correct -// signature. -// -// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error -// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence -// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison -// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -// -// The last link in particular show the method used below. -// -// For SFINAE to work with inherited methods, we need to pull some extra tricks -// with multiple inheritance. In the more standard formulation, the overloads -// of Check would be: -// -// template <typename C> -// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); -// -// template <typename C> -// No NotTheCheckWeWant(...); -// -// static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes); -// -// The problem here is that template resolution will not match -// C::TargetFunc if TargetFunc does not exist directly in C. That is, if -// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, -// |value| will be false. This formulation only checks for whether or -// not TargetFunc exist directly in the class being introspected. -// -// To get around this, we play a dirty trick with multiple inheritance. -// First, We create a class BaseMixin that declares each function that we -// want to probe for. Then we create a class Base that inherits from both T -// (the class we wish to probe) and BaseMixin. Note that the function -// signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(). -// -// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an -// ambiguous resolution between BaseMixin and T. This lets us write the -// following: -// -// template <typename C> -// No GoodCheck(Helper<&C::TargetFunc>*); -// -// template <typename C> -// Yes GoodCheck(...); -// -// static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes); -// -// Notice here that the variadic version of GoodCheck() returns Yes here -// instead of No like the previous one. Also notice that we calculate |value| -// by specializing GoodCheck() on Base instead of T. -// -// We've reversed the roles of the variadic, and Helper overloads. -// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid -// substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve -// to the variadic version if T has TargetFunc. If T::TargetFunc does not -// exist, then &C::TargetFunc is not ambiguous, and the overload resolution -// will prefer GoodCheck(Helper<&C::TargetFunc>*). -// -// This method of SFINAE will correctly probe for inherited names, but it cannot -// typecheck those names. It's still a good enough sanity check though. -// -// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. -// -// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted -// this works well. -// -// TODO(ajwong): Make this check for Release() as well. -// See http://crbug.com/82038. -template <typename T> -class SupportsAddRefAndRelease { - using Yes = char[1]; - using No = char[2]; - - struct BaseMixin { - void AddRef(); - }; - -// MSVC warns when you try to use Base if T has a private destructor, the -// common pattern for refcounted types. It does this even though no attempt to -// instantiate Base is made. We disable the warning for this definition. -#if defined(OS_WIN) -#pragma warning(push) -#pragma warning(disable:4624) -#endif - struct Base : public T, public BaseMixin { - }; -#if defined(OS_WIN) -#pragma warning(pop) -#endif - - template <void(BaseMixin::*)()> struct Helper {}; - - template <typename C> - static No& Check(Helper<&C::AddRef>*); - - template <typename > - static Yes& Check(...); - - public: - enum { value = sizeof(Check<Base>(0)) == sizeof(Yes) }; -}; - -// Helpers to assert that arguments of a recounted type are bound with a -// scoped_refptr. -template <bool IsClasstype, typename T> -struct UnsafeBindtoRefCountedArgHelper : std::false_type { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArgHelper<true, T> - : std::integral_constant<bool, SupportsAddRefAndRelease<T>::value> { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArg : std::false_type { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArg<T*> - : UnsafeBindtoRefCountedArgHelper<std::is_class<T>::value, T> { -}; template <typename T> -class HasIsMethodTag { - using Yes = char[1]; - using No = char[2]; - - template <typename U> - static Yes& Check(typename U::IsMethod*); +struct IsWeakReceiver; - template <typename U> - static No& Check(...); - - public: - enum { value = sizeof(Check<T>(0)) == sizeof(Yes) }; -}; +namespace internal { template <typename T> class UnretainedWrapper { @@ -315,22 +195,26 @@ class ConstRefWrapper { }; template <typename T> -struct IgnoreResultHelper { - explicit IgnoreResultHelper(T functor) : functor_(functor) {} - - T functor_; +class RetainedRefWrapper { + public: + explicit RetainedRefWrapper(T* o) : ptr_(o) {} + explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {} + T* get() const { return ptr_.get(); } + private: + scoped_refptr<T> ptr_; }; template <typename T> -struct IgnoreResultHelper<Callback<T> > { - explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {} +struct IgnoreResultHelper { + explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {} + explicit operator bool() const { return !!functor_; } - const Callback<T>& functor_; + T functor_; }; // An alternate implementation is to avoid the destructive copy, and instead // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to -// a class that is essentially a scoped_ptr<>. +// a class that is essentially a std::unique_ptr<>. // // The current implementation has the benefit though of leaving ParamTraits<> // fully in callback_internal.h as well as avoiding type conversions during @@ -341,7 +225,7 @@ class OwnedWrapper { explicit OwnedWrapper(T* o) : ptr_(o) {} ~OwnedWrapper() { delete ptr_; } T* get() const { return ptr_; } - OwnedWrapper(const OwnedWrapper& other) { + OwnedWrapper(OwnedWrapper&& other) { ptr_ = other.ptr_; other.ptr_ = NULL; } @@ -378,7 +262,7 @@ class PassedWrapper { public: explicit PassedWrapper(T&& scoper) : is_valid_(true), scoper_(std::move(scoper)) {} - PassedWrapper(const PassedWrapper& other) + PassedWrapper(PassedWrapper&& other) : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} T Take() const { CHECK(is_valid_); @@ -393,37 +277,32 @@ class PassedWrapper { // Unwrap the stored parameters for the wrappers above. template <typename T> -const T& Unwrap(const T& o) { - return o; +T&& Unwrap(T&& o) { + return std::forward<T>(o); } template <typename T> -T* Unwrap(UnretainedWrapper<T> unretained) { +T* Unwrap(const UnretainedWrapper<T>& unretained) { return unretained.get(); } template <typename T> -const T& Unwrap(ConstRefWrapper<T> const_ref) { +const T& Unwrap(const ConstRefWrapper<T>& const_ref) { return const_ref.get(); } template <typename T> -T* Unwrap(const scoped_refptr<T>& o) { +T* Unwrap(const RetainedRefWrapper<T>& o) { return o.get(); } template <typename T> -const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { - return o; -} - -template <typename T> T* Unwrap(const OwnedWrapper<T>& o) { return o.get(); } template <typename T> -T Unwrap(PassedWrapper<T>& o) { +T Unwrap(const PassedWrapper<T>& o) { return o.Take(); } @@ -434,16 +313,11 @@ T Unwrap(PassedWrapper<T>& o) { // // The first argument should be the type of the object that will be received by // the method. -template <bool IsMethod, typename... Args> -struct IsWeakMethod : public std::false_type {}; +template <bool is_method, typename... Args> +struct IsWeakMethod : std::false_type {}; template <typename T, typename... Args> -struct IsWeakMethod<true, WeakPtr<T>, Args...> : public std::true_type {}; - -template <typename T, typename... Args> -struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...> - : public std::true_type {}; - +struct IsWeakMethod<true, T, Args...> : IsWeakReceiver<T> {}; // Packs a list of types to hold them in a single type. template <typename... Types> @@ -526,19 +400,25 @@ struct MakeFunctionTypeImpl<R, TypeList<Args...>> { template <typename R, typename ArgList> using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type; -// Used for ExtractArgs. +// Used for ExtractArgs and ExtractReturnType. template <typename Signature> struct ExtractArgsImpl; template <typename R, typename... Args> struct ExtractArgsImpl<R(Args...)> { - using Type = TypeList<Args...>; + using ReturnType = R; + using ArgsList = TypeList<Args...>; }; // A type-level function that extracts function arguments into a TypeList. // E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>. template <typename Signature> -using ExtractArgs = typename ExtractArgsImpl<Signature>::Type; +using ExtractArgs = typename ExtractArgsImpl<Signature>::ArgsList; + +// A type-level function that extracts the return type of a function. +// E.g. ExtractReturnType<R(A, B, C)> is evaluated to R. +template <typename Signature> +using ExtractReturnType = typename ExtractArgsImpl<Signature>::ReturnType; } // namespace internal @@ -548,6 +428,16 @@ static inline internal::UnretainedWrapper<T> Unretained(T* o) { } template <typename T> +static inline internal::RetainedRefWrapper<T> RetainedRef(T* o) { + return internal::RetainedRefWrapper<T>(o); +} + +template <typename T> +static inline internal::RetainedRefWrapper<T> RetainedRef(scoped_refptr<T> o) { + return internal::RetainedRefWrapper<T>(std::move(o)); +} + +template <typename T> static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { return internal::ConstRefWrapper<T>(o); } @@ -577,22 +467,36 @@ static inline internal::PassedWrapper<T> Passed(T* scoper) { template <typename T> static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { - return internal::IgnoreResultHelper<T>(data); + return internal::IgnoreResultHelper<T>(std::move(data)); } -template <typename T> -static inline internal::IgnoreResultHelper<Callback<T> > -IgnoreResult(const Callback<T>& data) { - return internal::IgnoreResultHelper<Callback<T> >(data); -} - -void DoNothing(); +BASE_EXPORT void DoNothing(); template<typename T> void DeletePointer(T* obj) { delete obj; } +// An injection point to control |this| pointer behavior on a method invocation. +// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a +// method, base::Bind cancels the method invocation if the receiver is tested as +// false. +// E.g. Foo::bar() is not called: +// struct Foo : base::SupportsWeakPtr<Foo> { +// void bar() {} +// }; +// +// WeakPtr<Foo> oo = nullptr; +// base::Bind(&Foo::bar, oo).Run(); +template <typename T> +struct IsWeakReceiver : std::false_type {}; + +template <typename T> +struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {}; + +template <typename T> +struct IsWeakReceiver<WeakPtr<T>> : std::true_type {}; + } // namespace base #endif // BASE_BIND_HELPERS_H_ |