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

Side by Side Diff: base/callback.h

Issue 2042223002: Introduce OnceClosure and BindOnce (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: swap Once & Repeating positions Created 4 years, 3 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 unified diff | Download patch
« no previous file with comments | « base/bind_unittest.cc ('k') | base/callback_forward.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_CALLBACK_H_ 5 #ifndef BASE_CALLBACK_H_
6 #define BASE_CALLBACK_H_ 6 #define BASE_CALLBACK_H_
7 7
8 #include "base/callback_forward.h" 8 #include "base/callback_forward.h"
9 #include "base/callback_internal.h" 9 #include "base/callback_internal.h"
10 10
11 // NOTE: Header files that do not require the full definition of Callback or 11 // NOTE: Header files that do not require the full definition of Callback or
12 // Closure should #include "base/callback_forward.h" instead of this file. 12 // Closure should #include "base/callback_forward.h" instead of this file.
13 13
14 // ----------------------------------------------------------------------------- 14 // -----------------------------------------------------------------------------
15 // Usage documentation 15 // Usage documentation
16 // ----------------------------------------------------------------------------- 16 // -----------------------------------------------------------------------------
17 // 17 //
18 // See //docs/callback.md for documentation. 18 // See //docs/callback.md for documentation.
19 19
20 namespace base { 20 namespace base {
21 21
22 template <typename R, typename... Args, internal::CopyMode copy_mode> 22 namespace internal {
23 class Callback<R(Args...), copy_mode> 23
24 : public internal::CallbackBase<copy_mode> { 24 // RunMixin provides different variants of `Run()` function to `Callback<>`
25 // based on the type of callback.
26 template <typename CallbackType>
27 class RunMixin;
28
29 // Specialization for OnceCallback.
30 template <typename R, typename... Args>
31 class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>> {
32 private:
33 using CallbackType =
34 Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>;
35
25 public: 36 public:
26 using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...); 37 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
27 38
28 // MSVC 2013 doesn't support Type Alias of function types. 39 R Run(Args... args) && {
29 // Revisit this after we update it to newer version. 40 // Move the callback instance into a local variable before the invocation,
30 typedef R RunType(Args...); 41 // that ensures the internal state is cleared after the invocation.
42 // It's not safe to touch |this| after the invocation, since running the
43 // bound function may destroy |this|.
44 CallbackType cb = static_cast<CallbackType&&>(*this);
45 PolymorphicInvoke f =
46 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
47 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
48 }
49 };
50
51 // Specialization for RepeatingCallback.
52 template <typename R, typename... Args, CopyMode copy_mode>
53 class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> {
54 private:
55 using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>;
56
57 public:
58 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
59
60 R Run(Args... args) const {
61 const CallbackType& cb = static_cast<const CallbackType&>(*this);
62 PolymorphicInvoke f =
63 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
64 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
65 }
66 };
67
68 template <typename From, typename To>
69 struct IsCallbackConvertible : std::false_type {};
70
71 template <typename Signature>
72 struct IsCallbackConvertible<
73 Callback<Signature, CopyMode::Copyable, RepeatMode::Repeating>,
74 Callback<Signature, CopyMode::MoveOnly, RepeatMode::Once>> : std::true_type {
75 };
76
77 } // namespace internal
78
79 template <typename R,
80 typename... Args,
81 internal::CopyMode copy_mode,
82 internal::RepeatMode repeat_mode>
83 class Callback<R(Args...), copy_mode, repeat_mode>
84 : public internal::CallbackBase<copy_mode>,
85 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
86 public:
87 static_assert(repeat_mode != internal::RepeatMode::Once ||
88 copy_mode == internal::CopyMode::MoveOnly,
89 "OnceCallback must be MoveOnly.");
90
91 using RunType = R(Args...);
31 92
32 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} 93 Callback() : internal::CallbackBase<copy_mode>(nullptr) {}
33 94
34 explicit Callback(internal::BindStateBase* bind_state) 95 explicit Callback(internal::BindStateBase* bind_state)
35 : internal::CallbackBase<copy_mode>(bind_state) { 96 : internal::CallbackBase<copy_mode>(bind_state) {
36 } 97 }
37 98
99 template <typename OtherCallback,
100 typename = typename std::enable_if<
101 internal::IsCallbackConvertible<OtherCallback, Callback>::value
102 >::type>
103 Callback(OtherCallback other)
104 : internal::CallbackBase<copy_mode>(std::move(other)) {}
105
106 template <typename OtherCallback,
107 typename = typename std::enable_if<
108 internal::IsCallbackConvertible<OtherCallback, Callback>::value
109 >::type>
110 Callback& operator=(OtherCallback other) {
111 static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other);
112 return *this;
113 }
114
38 bool Equals(const Callback& other) const { 115 bool Equals(const Callback& other) const {
39 return this->EqualsInternal(other); 116 return this->EqualsInternal(other);
40 } 117 }
41 118
42 // Run() makes an extra copy compared to directly calling the bound function 119 friend class internal::RunMixin<Callback>;
43 // if an argument is passed-by-value and is copyable-but-not-movable:
44 // i.e. below copies CopyableNonMovableType twice.
45 // void F(CopyableNonMovableType) {}
46 // Bind(&F).Run(CopyableNonMovableType());
47 //
48 // We can not fully apply Perfect Forwarding idiom to the callchain from
49 // Callback::Run() to the target function. Perfect Forwarding requires
50 // knowing how the caller will pass the arguments. However, the signature of
51 // InvokerType::Run() needs to be fixed in the callback constructor, so Run()
52 // cannot template its arguments based on how it's called.
53 R Run(Args... args) const {
54 PolymorphicInvoke f =
55 reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
56 return f(this->bind_state_.get(), std::forward<Args>(args)...);
57 }
58 }; 120 };
59 121
60 } // namespace base 122 } // namespace base
61 123
62 #endif // BASE_CALLBACK_H_ 124 #endif // BASE_CALLBACK_H_
OLDNEW
« no previous file with comments | « base/bind_unittest.cc ('k') | base/callback_forward.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698