Index: base/callback.h |
diff --git a/base/callback.h b/base/callback.h |
index 05a7182c3d07c175230ef274f7c55afdf46db340..3434d322723217f35b8d8cb8d1d53cafc4ff187b 100644 |
--- a/base/callback.h |
+++ b/base/callback.h |
@@ -212,6 +212,46 @@ |
namespace base { |
+namespace internal { |
+ |
+// Holds the methods that don't require specialization to reduce template bloat. |
+class CallbackBase { |
+ 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); |
+ |
+ public: |
+ explicit CallbackBase(InvokeFuncStorage polymorphic_invoke) |
willchan no longer on Chromium
2011/02/17 01:09:57
Can't this be protected? And then you can move all
awong
2011/02/17 02:05:29
Good point. Fixed.
|
+ : polymorphic_invoke_(polymorphic_invoke) { |
+ } |
+ |
+ // Returns true if Callback is empty (doesn't refer to anything). |
+ bool is_empty() const { |
willchan no longer on Chromium
2011/02/17 01:09:57
Bike shed alert: I prefer empty() to is_empty(). F
awong
2011/02/17 02:05:29
Yeah...now that you mention it, empty() is my pref
|
+ return invoker_storage_.get() == NULL; |
+ } |
+ |
+ // Returns the Callback into an empty state. |
+ void reset() { |
+ invoker_storage_ = NULL; |
+ polymorphic_invoke_ = NULL; |
+ } |
+ |
+ bool Equals(const CallbackBase& other) const { |
akalin
2011/02/17 01:16:39
Do we really need this? I have a hard time imagin
awong
2011/02/17 02:05:29
I struggled with this...I almost actually wanted t
|
+ return invoker_storage_.get() == other.invoker_storage_.get() && |
+ polymorphic_invoke_ == other.polymorphic_invoke_; |
+ } |
+ |
+ protected: |
+ 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 +261,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) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -238,25 +277,26 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(invoker_holder.invoker_storage_); |
akalin
2011/02/17 01:16:39
can't you add an InvokerStorageBase param to the C
awong
2011/02/17 02:05:29
Oh...good point.
|
} |
- R Run(void) const { |
- return polymorphic_invoke_(invoker_storage_.get()); |
- } |
- private: |
- scoped_refptr<internal::InvokerStorageBase> invoker_storage_; |
- PolymorphicInvoke polymorphic_invoke_; |
+ R Run() const { |
+ PolymorphicInvoke f = |
+ reinterpret_cast<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) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -267,26 +307,27 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(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) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -297,29 +338,30 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(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) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -330,32 +372,33 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(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) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -366,28 +409,29 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(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 +439,7 @@ class Callback<R(A1, A2, A3, A4, A5)> { |
const A4&, |
const A5&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -406,30 +450,31 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(invoker_holder.invoker_storage_); |
} |
+ |
R Run(const A1& a1, |
const A2& a2, |
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 +483,7 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> { |
const A5&, |
const A6&); |
- Callback() : polymorphic_invoke_(NULL) { } |
+ Callback() : CallbackBase(NULL) { } |
// We pass InvokerStorageHolder by const ref to avoid incurring an |
// unnecessary AddRef/Unref pair even though we will modify the object. |
@@ -449,27 +494,28 @@ 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) { |
+ : CallbackBase( |
+ reinterpret_cast<InvokeFuncStorage>(&T::FunctionTraits::DoInvoke)) { |
invoker_storage_.swap(invoker_holder.invoker_storage_); |
} |
+ |
R Run(const A1& a1, |
const A2& a2, |
const A3& a3, |
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_; |
}; |