summaryrefslogtreecommitdiffstats
path: root/base/bind_helpers.h
diff options
context:
space:
mode:
authorajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-21 19:23:44 +0000
committerajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-21 19:23:44 +0000
commit7296f2763bd40e560466f09836c7208c42d90f94 (patch)
tree142a03c36f75f42738206355a029707ad88cdffc /base/bind_helpers.h
parent1fbbf963079bc977ea041b7e50ddf4666f6fec38 (diff)
downloadchromium_src-7296f2763bd40e560466f09836c7208c42d90f94.zip
chromium_src-7296f2763bd40e560466f09836c7208c42d90f94.tar.gz
chromium_src-7296f2763bd40e560466f09836c7208c42d90f94.tar.bz2
Callback API Change: Reimplement Bind(); support IgnoreResult, full currying, and use less types.
The main API change IgnoreResult() and fully currying. See unittest for what the new API looks like. The rest of the changes are done to support that. Previously, IgnoreReturn could not be used with WeakPtr<> Bind()s as it was applied after the fact to the Callback object. Now, IgnoreResult() wraps the function like Unretained(). As an incidental benefit, the new implementation gave us fully currying for free. Also, the new implementation scales better when supporting higher arities of functions. The new type growth is: (n^2 + 20n) / 2 as opposed to (3n^2 + 17n) / 2 where n == arity. For n = 6 and n=10, the new implementation has 81 and 155 templates respectively. The old implementation had 105 and 235 templates respectively. BUG=35233,98919,98542 TEST=existing unittests Review URL: http://codereview.chromium.org/8483003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110975 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/bind_helpers.h')
-rw-r--r--base/bind_helpers.h123
1 files changed, 98 insertions, 25 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index d7ddb2c..6e0f8fe 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -198,7 +198,6 @@ class SupportsAddRefAndRelease {
static const bool 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>
@@ -219,6 +218,20 @@ struct UnsafeBindtoRefCountedArg<T*>
: UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
};
+template <typename T>
+class HasIsMethodTag {
+ typedef char Yes[1];
+ typedef char No[2];
+
+ template <typename U>
+ static Yes& Check(typename U::IsMethod*);
+
+ template <typename U>
+ static No& Check(...);
+
+ public:
+ static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
+};
template <typename T>
class UnretainedWrapper {
@@ -238,6 +251,20 @@ class ConstRefWrapper {
const T* ptr_;
};
+template <typename T>
+struct IgnoreResultHelper {
+ explicit IgnoreResultHelper(T functor) : functor_(functor) {}
+
+ T functor_;
+};
+
+template <typename T>
+struct IgnoreResultHelper<Callback<T> > {
+ explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {}
+
+ const Callback<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<>.
@@ -260,61 +287,80 @@ class OwnedWrapper {
mutable T* ptr_;
};
-
// Unwrap the stored parameters for the wrappers above.
template <typename T>
-T Unwrap(T o) { return o; }
+struct UnwrapTraits {
+ typedef const T& ForwardType;
+ static ForwardType Unwrap(const T& o) { return o; }
+};
template <typename T>
-T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); }
+struct UnwrapTraits<UnretainedWrapper<T> > {
+ typedef T* ForwardType;
+ static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
+ return unretained.get();
+ }
+};
template <typename T>
-const T& Unwrap(ConstRefWrapper<T> const_ref) {
- return const_ref.get();
-}
+struct UnwrapTraits<ConstRefWrapper<T> > {
+ typedef const T& ForwardType;
+ static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
+ return const_ref.get();
+ }
+};
template <typename T>
-T* Unwrap(const scoped_refptr<T>& o) { return o.get(); }
+struct UnwrapTraits<scoped_refptr<T> > {
+ typedef T* ForwardType;
+ static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
+};
template <typename T>
-const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; }
+struct UnwrapTraits<WeakPtr<T> > {
+ typedef const WeakPtr<T>& ForwardType;
+ static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
+};
template <typename T>
-T* Unwrap(const OwnedWrapper<T>& o) {
- return o.get();
-}
+struct UnwrapTraits<OwnedWrapper<T> > {
+ typedef T* ForwardType;
+ static ForwardType Unwrap(const OwnedWrapper<T>& o) {
+ return o.get();
+ }
+};
// Utility for handling different refcounting semantics in the Bind()
// function.
-template <typename IsMethod, typename T>
+template <bool, typename T>
struct MaybeRefcount;
template <typename T>
-struct MaybeRefcount<base::false_type, T> {
+struct MaybeRefcount<false, T> {
static void AddRef(const T&) {}
static void Release(const T&) {}
};
template <typename T, size_t n>
-struct MaybeRefcount<base::false_type, T[n]> {
+struct MaybeRefcount<false, T[n]> {
static void AddRef(const T*) {}
static void Release(const T*) {}
};
template <typename T>
-struct MaybeRefcount<base::true_type, T*> {
+struct MaybeRefcount<true, T*> {
static void AddRef(T* o) { o->AddRef(); }
static void Release(T* o) { o->Release(); }
};
template <typename T>
-struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > {
+struct MaybeRefcount<true, UnretainedWrapper<T> > {
static void AddRef(const UnretainedWrapper<T>&) {}
static void Release(const UnretainedWrapper<T>&) {}
};
template <typename T>
-struct MaybeRefcount<base::true_type, OwnedWrapper<T> > {
+struct MaybeRefcount<true, OwnedWrapper<T> > {
static void AddRef(const OwnedWrapper<T>&) {}
static void Release(const OwnedWrapper<T>&) {}
};
@@ -322,19 +368,19 @@ struct MaybeRefcount<base::true_type, OwnedWrapper<T> > {
// No need to additionally AddRef() and Release() since we are storing a
// scoped_refptr<> inside the storage object already.
template <typename T>
-struct MaybeRefcount<base::true_type, scoped_refptr<T> > {
+struct MaybeRefcount<true, scoped_refptr<T> > {
static void AddRef(const scoped_refptr<T>& o) {}
static void Release(const scoped_refptr<T>& o) {}
};
template <typename T>
-struct MaybeRefcount<base::true_type, const T*> {
+struct MaybeRefcount<true, const T*> {
static void AddRef(const T* o) { o->AddRef(); }
static void Release(const T* o) { o->Release(); }
};
template <typename T>
-struct MaybeRefcount<base::true_type, WeakPtr<T> > {
+struct MaybeRefcount<true, WeakPtr<T> > {
static void AddRef(const WeakPtr<T>&) {}
static void Release(const WeakPtr<T>&) {}
};
@@ -344,28 +390,55 @@ 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
+// InvokeHelper that will no-op itself in the event the WeakPtr<> for
+// the target object is invalidated.
+//
+// P1 should be the type of the object that will be received of the method.
+template <bool IsMethod, typename P1>
+struct IsWeakMethod : public false_type {};
+
+template <typename T>
+struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
+
+template <typename T>
+struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
+
} // namespace internal
template <typename T>
-inline internal::UnretainedWrapper<T> Unretained(T* o) {
+static inline internal::UnretainedWrapper<T> Unretained(T* o) {
return internal::UnretainedWrapper<T>(o);
}
template <typename T>
-inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
+static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
return internal::ConstRefWrapper<T>(o);
}
template <typename T>
-inline internal::OwnedWrapper<T> Owned(T* o) {
+static inline internal::OwnedWrapper<T> Owned(T* o) {
return internal::OwnedWrapper<T>(o);
}
template <typename R>
-Closure IgnoreReturn(Callback<R(void)> callback) {
+static inline Closure IgnoreReturn(Callback<R(void)> callback) {
return Bind(&internal::VoidReturnAdapter<R>, callback);
}
+template <typename T>
+static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
+ return internal::IgnoreResultHelper<T>(data);
+}
+
+template <typename T>
+static inline internal::IgnoreResultHelper<Callback<T> >
+IgnoreResult(const Callback<T>& data) {
+ return internal::IgnoreResultHelper<Callback<T> >(data);
+}
+
+
} // namespace base
#endif // BASE_BIND_HELPERS_H_