Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2759)

Unified Diff: base/callback.h

Issue 2042223002: Introduce OnceClosure and BindOnce (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« base/bind.h ('K') | « base/bind_unittest.cc ('k') | base/callback_forward.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698