aboutsummaryrefslogtreecommitdiff
path: root/third_party/chromium/base/bind_helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/chromium/base/bind_helpers.h')
-rw-r--r--third_party/chromium/base/bind_helpers.h268
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_