summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/bind_helpers.h9
-rw-r--r--base/bind_internal.h569
-rw-r--r--base/bind_internal.h.pump63
-rw-r--r--base/bind_internal_win.h40
-rw-r--r--base/bind_internal_win.h.pump4
-rw-r--r--base/bind_unittest.cc52
-rw-r--r--base/callback.h2
-rw-r--r--base/callback.h.pump8
-rw-r--r--base/template_util.h5
9 files changed, 676 insertions, 76 deletions
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index 73fd81e..e4b4a17 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -52,6 +52,7 @@
#pragma once
#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
namespace base {
@@ -215,7 +216,7 @@ const T& Unwrap(ConstRefWrapper<T> const_ref) {
// Utility for handling different refcounting semantics in the Bind()
// function.
-template <typename ref, typename T>
+template <typename IsMethod, typename T>
struct MaybeRefcount;
template <typename T>
@@ -248,6 +249,12 @@ struct MaybeRefcount<base::true_type, const T*> {
static void Release(const T* o) { o->Release(); }
};
+template <typename T>
+struct MaybeRefcount<base::true_type, WeakPtr<T> > {
+ static void AddRef(const WeakPtr<T>&) {}
+ static void Release(const WeakPtr<T>&) {}
+};
+
} // namespace internal
template <typename T>
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 606e2b0..203a286 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -14,6 +14,7 @@
#include "base/bind_helpers.h"
#include "base/callback_internal.h"
+#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
@@ -39,10 +40,21 @@ namespace internal {
// a calback.
// InvokerStorageN<> -- Provides storage for the bound parameters, and
// typedefs to the above.
+// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>.
//
// More details about the design of each class is included in a comment closer
// to their defition.
+
+// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an
+// object. It is used to select an InvokerN that will no-op itself in the
+// event the WeakPtr<> for the target object is invalidated.
+template <bool IsMethod, typename T>
+struct IsWeakMethod : public false_type {};
+
+template <typename T>
+struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
+
// FunctionTraits<>
//
// The FunctionTraits<> template determines the type of function, and also
@@ -75,6 +87,8 @@ struct FunctionTraits<R(*)()> {
typedef R (*NormalizedSig)();
typedef false_type IsMethod;
+ typedef R Return;
+
};
// Method: Arity 0.
@@ -83,6 +97,8 @@ struct FunctionTraits<R(T::*)()> {
typedef R (T::*NormalizedSig)();
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
@@ -94,6 +110,8 @@ struct FunctionTraits<R(T::*)() const> {
typedef R (T::*NormalizedSig)();
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
@@ -104,6 +122,9 @@ template <typename R, typename X1>
struct FunctionTraits<R(*)(X1)> {
typedef R (*NormalizedSig)(X1);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
@@ -115,6 +136,8 @@ struct FunctionTraits<R(T::*)(X1)> {
typedef R (T::*NormalizedSig)(X1);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -127,6 +150,8 @@ struct FunctionTraits<R(T::*)(X1) const> {
typedef R (T::*NormalizedSig)(X1);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -138,6 +163,9 @@ template <typename R, typename X1, typename X2>
struct FunctionTraits<R(*)(X1, X2)> {
typedef R (*NormalizedSig)(X1, X2);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -150,6 +178,8 @@ struct FunctionTraits<R(T::*)(X1, X2)> {
typedef R (T::*NormalizedSig)(X1, X2);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -163,6 +193,8 @@ struct FunctionTraits<R(T::*)(X1, X2) const> {
typedef R (T::*NormalizedSig)(X1, X2);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -175,6 +207,9 @@ template <typename R, typename X1, typename X2, typename X3>
struct FunctionTraits<R(*)(X1, X2, X3)> {
typedef R (*NormalizedSig)(X1, X2, X3);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -188,6 +223,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3)> {
typedef R (T::*NormalizedSig)(X1, X2, X3);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -202,6 +239,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3) const> {
typedef R (T::*NormalizedSig)(X1, X2, X3);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -215,6 +254,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4>
struct FunctionTraits<R(*)(X1, X2, X3, X4)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -230,6 +272,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -246,6 +290,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -261,6 +307,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -277,6 +326,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -294,6 +345,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -310,6 +363,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -327,6 +383,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -345,6 +403,8 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> {
typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
typedef X1 B2;
@@ -376,12 +436,12 @@ struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> {
// templates classes in the system to only have as many specializations as
// the max arity of function we wish to support.
-template <typename StorageType, typename NormalizedSig>
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker0;
// Function: Arity 0 -> 0.
template <typename StorageType, typename R>
-struct Invoker0<StorageType, R(*)()> {
+struct Invoker0<false, StorageType, R(*)()> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_();
@@ -390,7 +450,7 @@ struct Invoker0<StorageType, R(*)()> {
// Function: Arity 1 -> 1.
template <typename StorageType, typename R,typename X1>
-struct Invoker0<StorageType, R(*)(X1)> {
+struct Invoker0<false, StorageType, R(*)(X1)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -400,7 +460,7 @@ struct Invoker0<StorageType, R(*)(X1)> {
// Function: Arity 2 -> 2.
template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker0<StorageType, R(*)(X1, X2)> {
+struct Invoker0<false, StorageType, R(*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2) {
@@ -412,7 +472,7 @@ struct Invoker0<StorageType, R(*)(X1, X2)> {
// Function: Arity 3 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3>
-struct Invoker0<StorageType, R(*)(X1, X2, X3)> {
+struct Invoker0<false, StorageType, R(*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -425,7 +485,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3)> {
// Function: Arity 4 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4>
-struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> {
+struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -439,7 +499,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> {
// Function: Arity 5 -> 5.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -454,7 +514,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Function: Arity 6 -> 6.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -467,12 +527,12 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker1;
// Function: Arity 1 -> 0.
template <typename StorageType, typename R,typename X1>
-struct Invoker1<StorageType, R(*)(X1)> {
+struct Invoker1<false, StorageType, R(*)(X1)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_));
@@ -481,16 +541,29 @@ struct Invoker1<StorageType, R(*)(X1)> {
// Method: Arity 0 -> 0.
template <typename StorageType, typename R, typename T>
-struct Invoker1<StorageType, R(T::*)()> {
+struct Invoker1<false, StorageType, R(T::*)()> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)();
}
};
+// WeakPtr Method: Arity 0 -> 0.
+template <typename StorageType, typename T>
+struct Invoker1<true, StorageType, void(T::*)()> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)();
+ }
+};
+
// Function: Arity 2 -> 1.
template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker1<StorageType, R(*)(X1, X2)> {
+struct Invoker1<false, StorageType, R(*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -500,7 +573,7 @@ struct Invoker1<StorageType, R(*)(X1, X2)> {
// Method: Arity 1 -> 1.
template <typename StorageType, typename R, typename T, typename X1>
-struct Invoker1<StorageType, R(T::*)(X1)> {
+struct Invoker1<false, StorageType, R(T::*)(X1)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -508,10 +581,24 @@ struct Invoker1<StorageType, R(T::*)(X1)> {
}
};
+// WeakPtr Method: Arity 1 -> 1.
+template <typename StorageType, typename T, typename X1>
+struct Invoker1<true, StorageType, void(T::*)(X1)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X1>::ForwardType x1) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(x1);
+ }
+};
+
// Function: Arity 3 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3>
-struct Invoker1<StorageType, R(*)(X1, X2, X3)> {
+struct Invoker1<false, StorageType, R(*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3) {
@@ -523,7 +610,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3)> {
// Method: Arity 2 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
typename X2>
-struct Invoker1<StorageType, R(T::*)(X1, X2)> {
+struct Invoker1<false, StorageType, R(T::*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2) {
@@ -532,10 +619,25 @@ struct Invoker1<StorageType, R(T::*)(X1, X2)> {
}
};
+// WeakPtr Method: Arity 2 -> 2.
+template <typename StorageType, typename T, typename X1, typename X2>
+struct Invoker1<true, StorageType, void(T::*)(X1, X2)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X1>::ForwardType x1,
+ typename internal::ParamTraits<X2>::ForwardType x2) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(x1, x2);
+ }
+};
+
// Function: Arity 4 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4>
-struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> {
+struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3,
@@ -548,7 +650,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> {
// Method: Arity 3 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3>
-struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> {
+struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -558,10 +660,27 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> {
}
};
+// WeakPtr Method: Arity 3 -> 3.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3>
+struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X1>::ForwardType x1,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(x1, x2, x3);
+ }
+};
+
// Function: Arity 5 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3,
@@ -575,7 +694,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Method: Arity 4 -> 4.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4>
-struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> {
+struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -586,10 +705,28 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> {
}
};
+// WeakPtr Method: Arity 4 -> 4.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4>
+struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X1>::ForwardType x1,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(x1, x2, x3, x4);
+ }
+};
+
// Function: Arity 6 -> 5.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3,
@@ -604,7 +741,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 5.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X1>::ForwardType x1,
typename internal::ParamTraits<X2>::ForwardType x2,
@@ -616,12 +753,31 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+// WeakPtr Method: Arity 5 -> 5.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X1>::ForwardType x1,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4,
+ typename internal::ParamTraits<X5>::ForwardType x5) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(x1, x2, x3, x4, x5);
+ }
+};
+
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker2;
// Function: Arity 2 -> 0.
template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker2<StorageType, R(*)(X1, X2)> {
+struct Invoker2<false, StorageType, R(*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_));
@@ -630,17 +786,30 @@ struct Invoker2<StorageType, R(*)(X1, X2)> {
// Method: Arity 1 -> 0.
template <typename StorageType, typename R, typename T, typename X1>
-struct Invoker2<StorageType, R(T::*)(X1)> {
+struct Invoker2<false, StorageType, R(T::*)(X1)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_));
}
};
+// WeakPtr Method: Arity 1 -> 0.
+template <typename StorageType, typename T, typename X1>
+struct Invoker2<true, StorageType, void(T::*)(X1)> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_));
+ }
+};
+
// Function: Arity 3 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3>
-struct Invoker2<StorageType, R(*)(X1, X2, X3)> {
+struct Invoker2<false, StorageType, R(*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -651,7 +820,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3)> {
// Method: Arity 2 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
typename X2>
-struct Invoker2<StorageType, R(T::*)(X1, X2)> {
+struct Invoker2<false, StorageType, R(T::*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -659,10 +828,24 @@ struct Invoker2<StorageType, R(T::*)(X1, X2)> {
}
};
+// WeakPtr Method: Arity 2 -> 1.
+template <typename StorageType, typename T, typename X1, typename X2>
+struct Invoker2<true, StorageType, void(T::*)(X1, X2)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X2>::ForwardType x2) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2);
+ }
+};
+
// Function: Arity 4 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4>
-struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> {
+struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3,
typename internal::ParamTraits<X4>::ForwardType x4) {
@@ -674,7 +857,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> {
// Method: Arity 3 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3>
-struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> {
+struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3) {
@@ -683,10 +866,26 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> {
}
};
+// WeakPtr Method: Arity 3 -> 2.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3>
+struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3);
+ }
+};
+
// Function: Arity 5 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3,
typename internal::ParamTraits<X4>::ForwardType x4,
@@ -699,7 +898,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Method: Arity 4 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4>
-struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> {
+struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3,
@@ -710,10 +909,27 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> {
}
};
+// WeakPtr Method: Arity 4 -> 3.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4>
+struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4);
+ }
+};
+
// Function: Arity 6 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3,
typename internal::ParamTraits<X4>::ForwardType x4,
@@ -728,7 +944,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 4.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X2>::ForwardType x2,
typename internal::ParamTraits<X3>::ForwardType x3,
@@ -740,13 +956,31 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+// WeakPtr Method: Arity 5 -> 4.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X2>::ForwardType x2,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4,
+ typename internal::ParamTraits<X5>::ForwardType x5) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4, x5);
+ }
+};
+
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker3;
// Function: Arity 3 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3>
-struct Invoker3<StorageType, R(*)(X1, X2, X3)> {
+struct Invoker3<false, StorageType, R(*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
@@ -757,7 +991,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3)> {
// Method: Arity 2 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
typename X2>
-struct Invoker3<StorageType, R(T::*)(X1, X2)> {
+struct Invoker3<false, StorageType, R(T::*)(X1, X2)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
@@ -765,10 +999,23 @@ struct Invoker3<StorageType, R(T::*)(X1, X2)> {
}
};
+// WeakPtr Method: Arity 2 -> 0.
+template <typename StorageType, typename T, typename X1, typename X2>
+struct Invoker3<true, StorageType, void(T::*)(X1, X2)> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_));
+ }
+};
+
// Function: Arity 4 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4>
-struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> {
+struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X4>::ForwardType x4) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -780,7 +1027,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> {
// Method: Arity 3 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3>
-struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> {
+struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -789,10 +1036,25 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> {
}
};
+// WeakPtr Method: Arity 3 -> 1.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3>
+struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X3>::ForwardType x3) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3);
+ }
+};
+
// Function: Arity 5 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X4>::ForwardType x4,
typename internal::ParamTraits<X5>::ForwardType x5) {
@@ -805,7 +1067,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Method: Arity 4 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4>
-struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> {
+struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3,
typename internal::ParamTraits<X4>::ForwardType x4) {
@@ -815,10 +1077,27 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> {
}
};
+// WeakPtr Method: Arity 4 -> 2.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4>
+struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3,
+ x4);
+ }
+};
+
// Function: Arity 6 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X4>::ForwardType x4,
typename internal::ParamTraits<X5>::ForwardType x5,
@@ -832,7 +1111,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X3>::ForwardType x3,
typename internal::ParamTraits<X4>::ForwardType x4,
@@ -843,13 +1122,31 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+// WeakPtr Method: Arity 5 -> 3.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X3>::ForwardType x3,
+ typename internal::ParamTraits<X4>::ForwardType x4,
+ typename internal::ParamTraits<X5>::ForwardType x5) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3,
+ x4, x5);
+ }
+};
+
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker4;
// Function: Arity 4 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4>
-struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> {
+struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
@@ -860,7 +1157,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> {
// Method: Arity 3 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3>
-struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> {
+struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
@@ -868,10 +1165,25 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> {
}
};
+// WeakPtr Method: Arity 3 -> 0.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3>
+struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3)> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_));
+ }
+};
+
// Function: Arity 5 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X5>::ForwardType x5) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -883,7 +1195,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Method: Arity 4 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4>
-struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> {
+struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X4>::ForwardType x4) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -892,10 +1204,26 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> {
}
};
+// WeakPtr Method: Arity 4 -> 1.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4>
+struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X4>::ForwardType x4) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_), x4);
+ }
+};
+
// Function: Arity 6 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X5>::ForwardType x5,
typename internal::ParamTraits<X6>::ForwardType x6) {
@@ -908,7 +1236,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X4>::ForwardType x4,
typename internal::ParamTraits<X5>::ForwardType x5) {
@@ -918,13 +1246,30 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+// WeakPtr Method: Arity 5 -> 2.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X4>::ForwardType x4,
+ typename internal::ParamTraits<X5>::ForwardType x5) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_), x4, x5);
+ }
+};
+
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker5;
// Function: Arity 5 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5>
-struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> {
+struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
@@ -935,7 +1280,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> {
// Method: Arity 4 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4>
-struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> {
+struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
@@ -943,10 +1288,25 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> {
}
};
+// WeakPtr Method: Arity 4 -> 0.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4>
+struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4)> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_), Unwrap(invoker->p5_));
+ }
+};
+
// Function: Arity 6 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X6>::ForwardType x6) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -958,7 +1318,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base,
typename internal::ParamTraits<X5>::ForwardType x5) {
StorageType* invoker = static_cast<StorageType*>(base);
@@ -967,13 +1327,29 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
-template <typename StorageType, typename NormalizedSig>
+// WeakPtr Method: Arity 5 -> 1.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base,
+ typename internal::ParamTraits<X5>::ForwardType x5) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5);
+ }
+};
+
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker6;
// Function: Arity 6 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
typename X3, typename X4, typename X5, typename X6>
-struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
+struct Invoker6<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
@@ -985,7 +1361,7 @@ struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
// Method: Arity 5 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
typename X2, typename X3, typename X4, typename X5>
-struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
+struct Invoker6<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
static R DoInvoke(InvokerStorageBase* base) {
StorageType* invoker = static_cast<StorageType*>(base);
return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
@@ -994,6 +1370,20 @@ struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
}
};
+// WeakPtr Method: Arity 5 -> 0.
+template <typename StorageType, typename T, typename X1, typename X2,
+ typename X3, typename X4, typename X5>
+struct Invoker6<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> {
+ static void DoInvoke(InvokerStorageBase* base) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_),
+ Unwrap(invoker->p4_), Unwrap(invoker->p5_), Unwrap(invoker->p6_));
+ }
+};
// InvokerStorageN<>
//
@@ -1014,8 +1404,10 @@ class InvokerStorage0 : public InvokerStorageBase {
public:
typedef InvokerStorage0 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker0<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef Invoker0<false, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
@@ -1033,8 +1425,14 @@ class InvokerStorage1 : public InvokerStorageBase {
public:
typedef InvokerStorage1 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef Invoker1<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
@@ -1073,8 +1471,15 @@ class InvokerStorage2 : public InvokerStorageBase {
public:
typedef InvokerStorage2 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef ParamTraits<P2> P2Traits;
+ typedef Invoker2<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
@@ -1118,8 +1523,16 @@ class InvokerStorage3 : public InvokerStorageBase {
public:
typedef InvokerStorage3 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef ParamTraits<P2> P2Traits;
+ typedef ParamTraits<P3> P3Traits;
+ typedef Invoker3<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
@@ -1168,8 +1581,17 @@ class InvokerStorage4 : public InvokerStorageBase {
public:
typedef InvokerStorage4 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef ParamTraits<P2> P2Traits;
+ typedef ParamTraits<P3> P3Traits;
+ typedef ParamTraits<P4> P4Traits;
+ typedef Invoker4<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
@@ -1224,8 +1646,18 @@ class InvokerStorage5 : public InvokerStorageBase {
public:
typedef InvokerStorage5 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef ParamTraits<P2> P2Traits;
+ typedef ParamTraits<P3> P3Traits;
+ typedef ParamTraits<P4> P4Traits;
+ typedef ParamTraits<P5> P5Traits;
+ typedef Invoker5<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
@@ -1286,8 +1718,19 @@ class InvokerStorage6 : public InvokerStorageBase {
public:
typedef InvokerStorage6 StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+ typedef ParamTraits<P1> P1Traits;
+ typedef ParamTraits<P2> P2Traits;
+ typedef ParamTraits<P3> P3Traits;
+ typedef ParamTraits<P4> P4Traits;
+ typedef ParamTraits<P5> P5Traits;
+ typedef ParamTraits<P6> P6Traits;
+ typedef Invoker6<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
// For methods, we need to be careful for parameter 1. We skip the
// scoped_refptr check because the binder itself takes care of this. We also
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
index 4ccec5e..85875de 100644
--- a/base/bind_internal.h.pump
+++ b/base/bind_internal.h.pump
@@ -17,6 +17,7 @@ $var MAX_ARITY = 6
#include "base/bind_helpers.h"
#include "base/callback_internal.h"
+#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
@@ -42,10 +43,21 @@ namespace internal {
// a calback.
// InvokerStorageN<> -- Provides storage for the bound parameters, and
// typedefs to the above.
+// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>.
//
// More details about the design of each class is included in a comment closer
// to their defition.
+
+// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an
+// object. It is used to select an InvokerN that will no-op itself in the
+// event the WeakPtr<> for the target object is invalidated.
+template <bool IsMethod, typename T>
+struct IsWeakMethod : public false_type {};
+
+template <typename T>
+struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
+
// FunctionTraits<>
//
// The FunctionTraits<> template determines the type of function, and also
@@ -83,6 +95,8 @@ struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> {
typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
typedef false_type IsMethod;
+ typedef R Return;
+
$if ARITY > 0 [[
// Target type for each bound parameter.
@@ -102,6 +116,8 @@ struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> {
typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
@@ -119,6 +135,8 @@ struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> {
typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
typedef true_type IsMethod;
+ typedef R Return;
+
// Target type for each bound parameter.
typedef T B1;
@@ -154,7 +172,7 @@ $for ARG [[
$range BOUND 0..MAX_ARITY
$for BOUND [[
-template <typename StorageType, typename NormalizedSig>
+template <bool IsWeak, typename StorageType, typename NormalizedSig>
struct Invoker$(BOUND);
$range ARITY 0..MAX_ARITY
@@ -179,7 +197,7 @@ $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY
template <typename StorageType, typename R[[]]
$if ARITY > 0 [[,]][[]]
$for ARG , [[typename X$(ARG)]]>
-struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> {
+struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> {
static R DoInvoke(InvokerStorageBase* base[[]]
$if UNBOUND != 0 [[, ]][[]]
$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) {
@@ -196,7 +214,7 @@ $if BOUND > 0 [[
// Method: Arity $(M_ARITY) -> $(UNBOUND).
template <typename StorageType, typename R, typename T[[]]
$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
-struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
+struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
static R DoInvoke(InvokerStorageBase* base[[]]
$if UNBOUND > 0 [[, ]][[]]
$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
@@ -208,13 +226,31 @@ $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
}
};
+// WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND).
+template <typename StorageType, typename T[[]]
+$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
+struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])> {
+ static void DoInvoke(InvokerStorageBase* base[[]]
+$if UNBOUND > 0 [[, ]][[]]
+$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
+ StorageType* invoker = static_cast<StorageType*>(base);
+ typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
+ if (!weak_ptr.get()) {
+ return;
+ }
+ (weak_ptr->*invoker->f_)([[]]
+$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
+$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
+$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
+ }
+};
+
]] $$ if BOUND
]] $$ if UNBOUND
]] $$ for ARITY
]] $$ for BOUND
-
// InvokerStorageN<>
//
// These are the actual storage classes for the Invokers.
@@ -239,8 +275,25 @@ class InvokerStorage$(BOUND) : public InvokerStorageBase {
public:
typedef InvokerStorage$(BOUND) StorageType;
typedef FunctionTraits<Sig> TargetTraits;
- typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker;
typedef typename TargetTraits::IsMethod IsMethod;
+ typedef Sig Signature;
+
+$for BOUND_ARG [[
+ typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits;
+
+]]
+
+$if BOUND == 0 [[
+ typedef Invoker$(BOUND)<false, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+]] $else [[
+ typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
+ typename TargetTraits::NormalizedSig> Invoker;
+ COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
+ is_void<typename TargetTraits::Return>::value,
+ weak_ptrs_can_only_bind_to_methods_without_return_values);
+]]
+
$for BOUND_ARG [[
$if BOUND_ARG == 1 [[
diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h
index 85ba2ae..250f472 100644
--- a/base/bind_internal_win.h
+++ b/base/bind_internal_win.h
@@ -31,6 +31,8 @@ template <typename R>
struct FunctionTraits<R(__stdcall *)()> {
typedef R (*NormalizedSig)();
typedef false_type IsMethod;
+
+ typedef R Return;
};
// __fastcall Function: Arity 0.
@@ -38,6 +40,8 @@ template <typename R>
struct FunctionTraits<R(__fastcall *)()> {
typedef R (*NormalizedSig)();
typedef false_type IsMethod;
+
+ typedef R Return;
};
// __stdcall Function: Arity 1.
@@ -45,6 +49,9 @@ template <typename R, typename X1>
struct FunctionTraits<R(__stdcall *)(X1)> {
typedef R (*NormalizedSig)(X1);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
};
@@ -54,6 +61,9 @@ template <typename R, typename X1>
struct FunctionTraits<R(__fastcall *)(X1)> {
typedef R (*NormalizedSig)(X1);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
};
@@ -63,6 +73,9 @@ template <typename R, typename X1, typename X2>
struct FunctionTraits<R(__stdcall *)(X1, X2)> {
typedef R (*NormalizedSig)(X1, X2);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -73,6 +86,9 @@ template <typename R, typename X1, typename X2>
struct FunctionTraits<R(__fastcall *)(X1, X2)> {
typedef R (*NormalizedSig)(X1, X2);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -83,6 +99,9 @@ template <typename R, typename X1, typename X2, typename X3>
struct FunctionTraits<R(__stdcall *)(X1, X2, X3)> {
typedef R (*NormalizedSig)(X1, X2, X3);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -94,6 +113,9 @@ template <typename R, typename X1, typename X2, typename X3>
struct FunctionTraits<R(__fastcall *)(X1, X2, X3)> {
typedef R (*NormalizedSig)(X1, X2, X3);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -105,6 +127,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4>
struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -117,6 +142,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4>
struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -130,6 +158,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -144,6 +175,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -158,6 +192,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5, X6)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
@@ -173,6 +210,9 @@ template <typename R, typename X1, typename X2, typename X3, typename X4,
struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5, X6)> {
typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6);
typedef false_type IsMethod;
+
+ typedef R Return;
+
// Target type for each bound parameter.
typedef X1 B1;
typedef X2 B2;
diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump
index d293fcc..80ee37d 100644
--- a/base/bind_internal_win.h.pump
+++ b/base/bind_internal_win.h.pump
@@ -40,6 +40,8 @@ struct FunctionTraits<R(__stdcall *)($for ARG , [[X$(ARG)]])> {
typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
typedef false_type IsMethod;
+ typedef R Return;
+
$if ARITY > 0 [[
// Target type for each bound parameter.
@@ -58,6 +60,8 @@ struct FunctionTraits<R(__fastcall *)($for ARG , [[X$(ARG)]])> {
typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
typedef false_type IsMethod;
+ typedef R Return;
+
$if ARITY > 0 [[
// Target type for each bound parameter.
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index c131a86..d57f3d0 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -183,6 +183,10 @@ void RefArgSet(int &n) {
n = 2;
}
+int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
+ return n;
+}
+
// Only useful in no-compile tests.
int UnwrapNoRefParentRef(Parent& p) {
return p.value;
@@ -451,7 +455,7 @@ TEST_F(BindTest, SupportsAddRefAndRelease) {
}
// Unretained() wrapper support.
-// - Method bound to Unretained() non-object.
+// - Method bound to Unretained() non-const object.
// - Const method bound to Unretained() non-const object.
// - Const method bound to Unretained() const object.
TEST_F(BindTest, Unretained) {
@@ -471,6 +475,46 @@ TEST_F(BindTest, Unretained) {
const_method_const_ptr_cb.Run();
}
+// WeakPtr() support.
+// - Method bound to WeakPtr<> to non-const object.
+// - Const method bound to WeakPtr<> to non-const object.
+// - Const method bound to WeakPtr<> to const object.
+// - Normal Function with WeakPtr<> as P1 can have return type and is
+// not canceled.
+TEST_F(BindTest, WeakPtr) {
+ EXPECT_CALL(no_ref_, VoidMethod0());
+ EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
+
+ WeakPtrFactory<NoRef> weak_factory(&no_ref_);
+ WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
+
+ Callback<void(void)> method_cb =
+ Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
+ method_cb.Run();
+
+ Callback<void(void)> const_method_cb =
+ Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
+ const_method_cb.Run();
+
+ Callback<void(void)> const_method_const_ptr_cb =
+ Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
+ const_method_const_ptr_cb.Run();
+
+ Callback<int(int)> normal_func_cb =
+ Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
+ EXPECT_EQ(1, normal_func_cb.Run(1));
+
+ weak_factory.InvalidateWeakPtrs();
+ const_weak_factory.InvalidateWeakPtrs();
+
+ method_cb.Run();
+ const_method_cb.Run();
+ const_method_const_ptr_cb.Run();
+
+ // Still runs even after the pointers are invalidated.
+ EXPECT_EQ(2, normal_func_cb.Run(2));
+}
+
// ConstRef() wrapper support.
// - Binding w/o ConstRef takes a copy.
// - Binding a ConstRef takes a reference.
@@ -627,6 +671,12 @@ TEST_F(BindTest, NoCompile) {
// Callback<void(void)> ref_count_as_raw_ptr =
// Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr);
+ // - WeakPtrs cannot be bound to methods with return types.
+ // HasRef for_raw_ptr;
+ // WeakPtrFactory<NoRef> weak_factory(&no_ref_);
+ // Callback<int(void)> weak_ptr_with_non_void_return_type =
+ // Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr());
+
}
#if defined(OS_WIN)
diff --git a/base/callback.h b/base/callback.h
index 983fa7b02..fbd81d8 100644
--- a/base/callback.h
+++ b/base/callback.h
@@ -49,7 +49,7 @@
//
// void PrintHi() { LOG(INFO) << "hi."; }
// base::Closure void_func_cb = base::Bind(&PrintHi);
-// LOG(INFO) << void_func_cb.Run(); // Prints: hi.
+// void_func_cb.Run(); // Prints: hi.
//
// /* Binding a class method. */
// class Ref : public RefCountedThreadSafe<Ref> {
diff --git a/base/callback.h.pump b/base/callback.h.pump
index b565e38..cc45dd7 100644
--- a/base/callback.h.pump
+++ b/base/callback.h.pump
@@ -47,12 +47,12 @@ $var MAX_ARITY = 6
//
// /* Binding a normal function. */
// int Return5() { return 5; }
-// base::Callback<int(int)> func_cb = base::Bind(&Return5);
-// LOG(INFO) << func_cb.Run(5); // Prints 5.
+// base::Callback<int(void)> func_cb = base::Bind(&Return5);
+// LOG(INFO) << func_cb.Run(); // Prints 5.
//
// void PrintHi() { LOG(INFO) << "hi."; }
// base::Closure void_func_cb = base::Bind(&PrintHi);
-// LOG(INFO) << void_func_cb.Run(); // Prints: hi.
+// void_func_cb.Run(); // Prints: hi.
//
// /* Binding a class method. */
// class Ref : public RefCountedThreadSafe<Ref> {
@@ -191,7 +191,7 @@ $var MAX_ARITY = 6
//
// These are not features that are required in Chromium. Some of them, such as
// allowing for reference parameters, and subtyping of functions, may actually
-// because a source of errors. Removing support for these features actually
+// become a source of errors. Removing support for these features actually
// allows for a simpler implementation, and a terser Currying API.
//
//
diff --git a/base/template_util.h b/base/template_util.h
index e48af91..66e6a61 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -37,6 +37,9 @@ template <class T> struct is_non_const_reference : false_type {};
template <class T> struct is_non_const_reference<T&> : true_type {};
template <class T> struct is_non_const_reference<const T&> : false_type {};
+template <class T> struct is_void : false_type {};
+template <> struct is_void<void> : true_type {};
+
namespace internal {
// Types YesType and NoType are guaranteed such that sizeof(YesType) <