Chromium Code Reviews| 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_; |
| }; |