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

Side by Side Diff: base/callback.h

Issue 2753953003: Remove RunMixin from base::Callback implementation (Closed)
Patch Set: rebase Created 3 years, 9 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 | « no previous file | base/callback_unittest.cc » ('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 namespace internal { 22 namespace internal {
23 23
24 template <typename CallbackType>
25 struct IsOnceCallback : std::false_type {};
26
27 template <typename Signature>
28 struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {};
29
30 // RunMixin provides different variants of `Run()` function to `Callback<>`
31 // based on the type of callback.
32 template <typename CallbackType>
33 class RunMixin;
34
35 // Specialization for OnceCallback.
36 template <typename R, typename... Args>
37 class RunMixin<OnceCallback<R(Args...)>> {
38 private:
39 using CallbackType = OnceCallback<R(Args...)>;
40
41 public:
42 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
43
44 R Run(Args... args) const & {
45 // Note: even though this static_assert will trivially always fail, it
46 // cannot be simply replaced with static_assert(false, ...) because:
47 // - Per [dcl.dcl]/p4, a program is ill-formed if the constant-expression
48 // argument does not evaluate to true.
49 // - Per [temp.res]/p8, if no valid specialization can be generated for a
50 // template definition, and that template is not instantiated, the
51 // template definition is ill-formed, no diagnostic required.
52 // These two clauses, taken together, would allow a conforming C++ compiler
53 // to immediately reject static_assert(false, ...), even inside an
54 // uninstantiated template.
55 static_assert(!IsOnceCallback<CallbackType>::value,
56 "OnceCallback::Run() may only be invoked on a non-const "
57 "rvalue, i.e. std::move(callback).Run().");
58 }
59
60 R Run(Args... args) && {
61 // Move the callback instance into a local variable before the invocation,
62 // that ensures the internal state is cleared after the invocation.
63 // It's not safe to touch |this| after the invocation, since running the
64 // bound function may destroy |this|.
65 CallbackType cb = static_cast<CallbackType&&>(*this);
66 PolymorphicInvoke f =
67 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
68 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
69 }
70 };
71
72 // Specialization for RepeatingCallback.
73 template <typename R, typename... Args>
74 class RunMixin<RepeatingCallback<R(Args...)>> {
75 private:
76 using CallbackType = RepeatingCallback<R(Args...)>;
77
78 public:
79 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
80
81 R Run(Args... args) const {
82 const CallbackType& cb = static_cast<const CallbackType&>(*this);
83 PolymorphicInvoke f =
84 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
85 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
86 }
87 };
88
89 template <typename From, typename To> 24 template <typename From, typename To>
90 struct IsCallbackConvertible : std::false_type {}; 25 struct IsCallbackConvertible : std::false_type {};
91 26
92 template <typename Signature> 27 template <typename Signature>
93 struct IsCallbackConvertible<RepeatingCallback<Signature>, 28 struct IsCallbackConvertible<RepeatingCallback<Signature>,
94 OnceCallback<Signature>> : std::true_type {}; 29 OnceCallback<Signature>> : std::true_type {};
95 30
96 } // namespace internal 31 } // namespace internal
97 32
98 template <typename R, 33 template <typename R,
99 typename... Args, 34 typename... Args,
100 internal::CopyMode copy_mode, 35 internal::CopyMode copy_mode,
101 internal::RepeatMode repeat_mode> 36 internal::RepeatMode repeat_mode>
102 class Callback<R(Args...), copy_mode, repeat_mode> 37 class Callback<R(Args...), copy_mode, repeat_mode>
103 : public internal::CallbackBase<copy_mode>, 38 : public internal::CallbackBase<copy_mode> {
104 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
105 public: 39 public:
106 static_assert(repeat_mode != internal::RepeatMode::Once || 40 static_assert(repeat_mode != internal::RepeatMode::Once ||
107 copy_mode == internal::CopyMode::MoveOnly, 41 copy_mode == internal::CopyMode::MoveOnly,
108 "OnceCallback must be MoveOnly."); 42 "OnceCallback must be MoveOnly.");
109 43
110 using RunType = R(Args...); 44 using RunType = R(Args...);
45 using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...);
111 46
112 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} 47 Callback() : internal::CallbackBase<copy_mode>(nullptr) {}
113 48
114 explicit Callback(internal::BindStateBase* bind_state) 49 explicit Callback(internal::BindStateBase* bind_state)
115 : internal::CallbackBase<copy_mode>(bind_state) { 50 : internal::CallbackBase<copy_mode>(bind_state) {
116 } 51 }
117 52
118 template <typename OtherCallback, 53 template <typename OtherCallback,
119 typename = typename std::enable_if< 54 typename = typename std::enable_if<
120 internal::IsCallbackConvertible<OtherCallback, Callback>::value 55 internal::IsCallbackConvertible<OtherCallback, Callback>::value
121 >::type> 56 >::type>
122 Callback(OtherCallback other) 57 Callback(OtherCallback other)
123 : internal::CallbackBase<copy_mode>(std::move(other)) {} 58 : internal::CallbackBase<copy_mode>(std::move(other)) {}
124 59
125 template <typename OtherCallback, 60 template <typename OtherCallback,
126 typename = typename std::enable_if< 61 typename = typename std::enable_if<
127 internal::IsCallbackConvertible<OtherCallback, Callback>::value 62 internal::IsCallbackConvertible<OtherCallback, Callback>::value
128 >::type> 63 >::type>
129 Callback& operator=(OtherCallback other) { 64 Callback& operator=(OtherCallback other) {
130 static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other); 65 static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other);
131 return *this; 66 return *this;
132 } 67 }
133 68
134 bool Equals(const Callback& other) const { 69 bool Equals(const Callback& other) const {
135 return this->EqualsInternal(other); 70 return this->EqualsInternal(other);
136 } 71 }
137 72
138 friend class internal::RunMixin<Callback>; 73 R Run(Args... args) const & {
74 static_assert(repeat_mode == internal::RepeatMode::Repeating,
75 "OnceCallback::Run() may only be invoked on a non-const "
76 "rvalue, i.e. std::move(callback).Run().");
77
78 PolymorphicInvoke f =
79 reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
80 return f(this->bind_state_.get(), std::forward<Args>(args)...);
81 }
82
83 R Run(Args... args) && {
84 // Move the callback instance into a local variable before the invocation,
85 // that ensures the internal state is cleared after the invocation.
86 // It's not safe to touch |this| after the invocation, since running the
87 // bound function may destroy |this|.
88 Callback cb = std::move(*this);
89 PolymorphicInvoke f =
90 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
91 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
92 }
139 }; 93 };
140 94
141 } // namespace base 95 } // namespace base
142 96
143 #endif // BASE_CALLBACK_H_ 97 #endif // BASE_CALLBACK_H_
OLDNEW
« no previous file with comments | « no previous file | base/callback_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698