Index: base/callback.h |
diff --git a/base/callback.h b/base/callback.h |
index 05a7182c3d07c175230ef274f7c55afdf46db340..9e43afbef2a076159ba3f99db3261ef062b07b8c 100644 |
--- a/base/callback.h |
+++ b/base/callback.h |
@@ -212,6 +212,49 @@ |
namespace base { |
+namespace internal { |
+ |
+// Holds the methods that don't require specialization to reduce template bloat. |
+class CallbackBase { |
+ public: |
+ // Returns true if Callback is null (doesn't refer to anything). |
+ bool is_null() const { |
+ return invoker_storage_.get() == NULL; |
+ } |
+ |
+ // Returns the Callback into an uninitalized state. |
+ void Reset() { |
+ invoker_storage_ = NULL; |
+ polymorphic_invoke_ = NULL; |
+ } |
+ |
+ bool Equals(const CallbackBase& other) const { |
+ return invoker_storage_.get() == other.invoker_storage_.get() && |
+ polymorphic_invoke_ == other.polymorphic_invoke_; |
+ } |
+ |
+ protected: |
+ // In C++, it is safe to cast function pointers to function pointers of |
+ // another type. It is not okay to use void*. We create a InvokeFuncStorage |
+ // that that can store our function pointer, and then cast it back to |
+ // the original type on usage. |
+ typedef void(*InvokeFuncStorage)(void); |
+ |
+ CallbackBase(InvokeFuncStorage polymorphic_invoke, |
+ scoped_refptr<InvokerStorageBase>* invoker_storage) |
+ : polymorphic_invoke_(polymorphic_invoke) { |
+ if (invoker_storage) { |
+ invoker_storage_.swap(*invoker_storage); |
+ } |
+ } |
+ |
+ scoped_refptr<InvokerStorageBase> invoker_storage_; |
+ InvokeFuncStorage polymorphic_invoke_; |
+}; |
+ |
+} // namespace internal |
+ |
+ |
// First, we forward declare the Callback class template. This informs the |
// compiler that the template only has 1 type parameter which is the function |
// signature that the Callback is representing. |
@@ -221,13 +264,12 @@ namespace base { |
// only has one type: the function signature. |
template <typename Sig> |
class Callback; |
- |
template <typename R> |
-class Callback<R(void)> { |
+class Callback<R(void)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -238,25 +280,25 @@ class Callback<R(void)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
- R Run(void) const { |
- return polymorphic_invoke_(invoker_storage_.get()); |
- } |
+ R Run() const { |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ return f(invoker_storage_.get()); |
+ } |
}; |
template <typename R, typename A1> |
-class Callback<R(A1)> { |
+class Callback<R(A1)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -267,26 +309,26 @@ class Callback<R(A1)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1); |
- } |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ return f(invoker_storage_.get(), a1); |
+ } |
}; |
template <typename R, typename A1, typename A2> |
-class Callback<R(A1, A2)> { |
+class Callback<R(A1, A2)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, |
const A2&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -297,29 +339,29 @@ class Callback<R(A1, A2)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1, |
const A2& a2) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1, |
- a2); |
- } |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ return f(invoker_storage_.get(), a1, |
+ a2); |
+ } |
}; |
template <typename R, typename A1, typename A2, typename A3> |
-class Callback<R(A1, A2, A3)> { |
+class Callback<R(A1, A2, A3)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, |
const A2&, |
const A3&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -330,32 +372,32 @@ class Callback<R(A1, A2, A3)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1, |
const A2& a2, |
const A3& a3) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1, |
- a2, |
- a3); |
- } |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ return f(invoker_storage_.get(), a1, |
+ a2, |
+ a3); |
+ } |
}; |
template <typename R, typename A1, typename A2, typename A3, typename A4> |
-class Callback<R(A1, A2, A3, A4)> { |
+class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, |
const A2&, |
const A3&, |
const A4&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -366,28 +408,28 @@ class Callback<R(A1, A2, A3, A4)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1, |
const A2& a2, |
const A3& a3, |
const A4& a4) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1, |
- a2, |
- a3, |
- a4); |
- } |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ return f(invoker_storage_.get(), a1, |
+ a2, |
+ a3, |
+ a4); |
+ } |
}; |
template <typename R, typename A1, typename A2, typename A3, typename A4, |
typename A5> |
-class Callback<R(A1, A2, A3, A4, A5)> { |
+class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, |
const A2&, |
@@ -395,7 +437,7 @@ class Callback<R(A1, A2, A3, A4, A5)> { |
const A4&, |
const A5&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -406,8 +448,9 @@ class Callback<R(A1, A2, A3, A4, A5)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1, |
@@ -415,21 +458,20 @@ class Callback<R(A1, A2, A3, A4, A5)> { |
const A3& a3, |
const A4& a4, |
const A5& a5) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1, |
- a2, |
- a3, |
- a4, |
- a5); |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
+ |
+ return f(invoker_storage_.get(), a1, |
+ a2, |
+ a3, |
+ a4, |
+ a5); |
} |
- |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
}; |
template <typename R, typename A1, typename A2, typename A3, typename A4, |
typename A5, typename A6> |
-class Callback<R(A1, A2, A3, A4, A5, A6)> { |
+class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { |
public: |
typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&, |
const A2&, |
@@ -438,7 +480,7 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> { |
const A5&, |
const A6&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL, NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -449,8 +491,9 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> { |
// return the exact Callback<> type. See base/bind.h for details. |
template <typename T> |
Callback(const internal::InvokerStorageHolder<T>& invoker_holder) |
- : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { |
- invoker_storage_.swap(invoker_holder.invoker_storage_); |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke), |
+ &invoker_holder.invoker_storage_) { |
} |
R Run(const A1& a1, |
@@ -459,17 +502,16 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> { |
const A4& a4, |
const A5& a5, |
const A6& a6) const { |
- return polymorphic_invoke_(invoker_storage_.get(), a1, |
- a2, |
- a3, |
- a4, |
- a5, |
- a6); |
+ PolymorphicInvoke f = |
+ reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); |
+ |
+ return f(invoker_storage_.get(), a1, |
+ a2, |
+ a3, |
+ a4, |
+ a5, |
+ a6); |
} |
- |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
}; |