| Index: base/callback.h
|
| diff --git a/base/callback.h b/base/callback.h
|
| index e087c731d18e21d2628c8dda75ea69f81f8425b7..059beb4c99f9e852849c7f2d52e5690e06db0f92 100644
|
| --- a/base/callback.h
|
| +++ b/base/callback.h
|
| @@ -346,21 +346,70 @@
|
|
|
| namespace base {
|
|
|
| -template <typename R, typename... Args, internal::CopyMode copy_mode>
|
| -class Callback<R(Args...), copy_mode>
|
| - : public internal::CallbackBase<copy_mode> {
|
| +namespace internal {
|
| +
|
| +template <typename CallbackType>
|
| +class RunMixin;
|
| +
|
| +template <typename R, typename... Args, CopyMode copy_mode>
|
| +class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> {
|
| private:
|
| - using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...);
|
| + using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>;
|
| + using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
|
|
|
| public:
|
| - // MSVC 2013 doesn't support Type Alias of function types.
|
| - // Revisit this after we update it to newer version.
|
| - typedef R RunType(Args...);
|
| + R Run(Args... args) const {
|
| + const CallbackType* cb = static_cast<const CallbackType*>(this);
|
| + PolymorphicInvoke f =
|
| + reinterpret_cast<PolymorphicInvoke>(cb->polymorphic_invoke_);
|
| + return f(cb->bind_state_.get(), std::forward<Args>(args)...);
|
| + }
|
| +};
|
| +
|
| +template <typename R, typename... Args>
|
| +class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::OneShot>> {
|
| + private:
|
| + using CallbackType =
|
| + Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::OneShot>;
|
| + using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
|
| +
|
| + public:
|
| + R Run(Args... args) && {
|
| + CallbackType cb = std::move(*static_cast<CallbackType*>(this));
|
| + PolymorphicInvoke f =
|
| + reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke_);
|
| + return f(cb.bind_state_.get(), std::forward<Args>(args)...);
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +template <typename R,
|
| + typename... Args,
|
| + internal::CopyMode copy_mode,
|
| + internal::RepeatMode repeat_mode>
|
| +class Callback<R(Args...), copy_mode, repeat_mode>
|
| + : public internal::CallbackBase<copy_mode>,
|
| + public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
|
| + private:
|
| + static_assert(repeat_mode != internal::RepeatMode::OneShot ||
|
| + copy_mode == internal::CopyMode::MoveOnly,
|
| + "OneShot Callback must be MoveOnly.");
|
| + using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
|
| +
|
| + template <internal::CopyMode other_copy_mode,
|
| + internal::RepeatMode other_repeat_mode>
|
| + using EnableIfConvertibleFrom = std::enable_if<
|
| + (copy_mode != other_copy_mode || repeat_mode != other_repeat_mode) &&
|
| + (static_cast<int>(copy_mode) <= static_cast<int>(other_copy_mode)) &&
|
| + (static_cast<int>(repeat_mode) <= static_cast<int>(other_repeat_mode))>;
|
| +
|
| + public:
|
| + using RunType = R(Args...);
|
|
|
| Callback() : internal::CallbackBase<copy_mode>(nullptr) {}
|
|
|
| - Callback(internal::BindStateBase* bind_state,
|
| - PolymorphicInvoke invoke_func)
|
| + Callback(internal::BindStateBase* bind_state, PolymorphicInvoke invoke_func)
|
| : internal::CallbackBase<copy_mode>(bind_state) {
|
| using InvokeFuncStorage =
|
| typename internal::CallbackBase<copy_mode>::InvokeFuncStorage;
|
| @@ -368,26 +417,30 @@ class Callback<R(Args...), copy_mode>
|
| reinterpret_cast<InvokeFuncStorage>(invoke_func);
|
| }
|
|
|
| + template <
|
| + internal::CopyMode other_copy_mode,
|
| + internal::RepeatMode other_repeat_mode,
|
| + typename = typename EnableIfConvertibleFrom<other_copy_mode,
|
| + other_repeat_mode>::type>
|
| + Callback(Callback<R(Args...), other_copy_mode, other_repeat_mode> other)
|
| + : internal::CallbackBase<copy_mode>(std::move(other)) {}
|
| +
|
| + template <
|
| + internal::CopyMode other_copy_mode,
|
| + internal::RepeatMode other_repeat_mode,
|
| + typename = typename EnableIfConvertibleFrom<other_copy_mode,
|
| + other_repeat_mode>::type>
|
| + Callback& operator=(
|
| + Callback<R(Args...), other_copy_mode, other_repeat_mode> other) {
|
| + static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other);
|
| + return *this;
|
| + }
|
| +
|
| bool Equals(const Callback& other) const {
|
| return this->EqualsInternal(other);
|
| }
|
|
|
| - // Run() makes an extra copy compared to directly calling the bound function
|
| - // if an argument is passed-by-value and is copyable-but-not-movable:
|
| - // i.e. below copies CopyableNonMovableType twice.
|
| - // void F(CopyableNonMovableType) {}
|
| - // Bind(&F).Run(CopyableNonMovableType());
|
| - //
|
| - // We can not fully apply Perfect Forwarding idiom to the callchain from
|
| - // Callback::Run() to the target function. Perfect Forwarding requires
|
| - // knowing how the caller will pass the arguments. However, the signature of
|
| - // InvokerType::Run() needs to be fixed in the callback constructor, so Run()
|
| - // cannot template its arguments based on how it's called.
|
| - R Run(Args... args) const {
|
| - PolymorphicInvoke f =
|
| - reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke_);
|
| - return f(this->bind_state_.get(), std::forward<Args>(args)...);
|
| - }
|
| + friend class internal::RunMixin<Callback>;
|
| };
|
|
|
| } // namespace base
|
|
|