• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This defines helpful methods for dealing with Callbacks.  Because Callbacks
6 // are implemented using templates, with a class per callback signature, adding
7 // methods to Callback<> itself is unattractive (lots of extra code gets
8 // generated).  Instead, consider adding methods here.
9 
10 #ifndef BASE_FUNCTIONAL_CALLBACK_HELPERS_H_
11 #define BASE_FUNCTIONAL_CALLBACK_HELPERS_H_
12 
13 #include <atomic>
14 #include <memory>
15 #include <ostream>
16 #include <type_traits>
17 #include <utility>
18 
19 #include "base/atomicops.h"
20 #include "base/base_export.h"
21 #include "base/check.h"
22 #include "base/functional/bind.h"
23 #include "base/functional/callback.h"
24 #include "base/functional/callback_tags.h"
25 
26 namespace base {
27 
28 namespace internal {
29 
30 template <typename T>
31 struct IsBaseCallbackImpl : std::false_type {};
32 
33 template <typename R, typename... Args>
34 struct IsBaseCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
35 
36 template <typename R, typename... Args>
37 struct IsBaseCallbackImpl<RepeatingCallback<R(Args...)>> : std::true_type {};
38 
39 }  // namespace internal
40 
41 // IsBaseCallback<T> is satisfied if and only if T is an instantiation of
42 // base::OnceCallback<Signature> or base::RepeatingCallback<Signature>.
43 template <typename T>
44 concept IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>::value;
45 
46 namespace internal {
47 
48 template <typename... Args>
49 class OnceCallbackHolder final {
50  public:
51   OnceCallbackHolder(OnceCallback<void(Args...)> callback,
52                      bool ignore_extra_runs)
53       : callback_(std::move(callback)), ignore_extra_runs_(ignore_extra_runs) {
54     DCHECK(callback_);
55   }
56   OnceCallbackHolder(const OnceCallbackHolder&) = delete;
57   OnceCallbackHolder& operator=(const OnceCallbackHolder&) = delete;
58 
59   void Run(Args... args) {
60     if (has_run_.exchange(true, std::memory_order_relaxed)) {
61       CHECK(ignore_extra_runs_) << "Both OnceCallbacks returned by "
62                                    "base::SplitOnceCallback() were run. "
63                                    "At most one of the pair should be run.";
64       return;
65     }
66     DCHECK(callback_);
67     std::move(callback_).Run(std::forward<Args>(args)...);
68   }
69 
70  private:
71   std::atomic<bool> has_run_{false};
72   base::OnceCallback<void(Args...)> callback_;
73   const bool ignore_extra_runs_;
74 };
75 
76 template <typename... Args>
77 void ForwardRepeatingCallbacksImpl(
78     std::vector<RepeatingCallback<void(Args...)>> cbs,
79     Args... args) {
80   for (auto& cb : cbs) {
81     if (cb) {
82       cb.Run(std::forward<Args>(args)...);
83     }
84   }
85 }
86 
87 }  // namespace internal
88 
89 // Wraps the given RepeatingCallbacks and return one RepeatingCallbacks with an
90 // identical signature. On invocation of this callback, all the given
91 // RepeatingCallbacks will be called with the same arguments. Unbound arguments
92 // must be copyable.
93 template <typename... Args>
94 RepeatingCallback<void(Args...)> ForwardRepeatingCallbacks(
95     std::initializer_list<RepeatingCallback<void(Args...)>>&& cbs) {
96   std::vector<RepeatingCallback<void(Args...)>> v(
97       std::forward<std::initializer_list<RepeatingCallback<void(Args...)>>>(
98           cbs));
99   return BindRepeating(&internal::ForwardRepeatingCallbacksImpl<Args...>,
100                        std::move(v));
101 }
102 
103 // Wraps the given OnceCallback and returns two OnceCallbacks with an identical
104 // signature. On first invokation of either returned callbacks, the original
105 // callback is invoked. Invoking the remaining callback results in a crash.
106 template <typename... Args>
107 std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
108 SplitOnceCallback(OnceCallback<void(Args...)> callback) {
109   if (!callback) {
110     // Empty input begets two empty outputs.
111     return std::make_pair(OnceCallback<void(Args...)>(),
112                           OnceCallback<void(Args...)>());
113   }
114   using Helper = internal::OnceCallbackHolder<Args...>;
115   auto wrapped_once = base::BindRepeating(
116       &Helper::Run, std::make_unique<Helper>(std::move(callback),
117                                              /*ignore_extra_runs=*/false));
118   return std::make_pair(wrapped_once, wrapped_once);
119 }
120 
121 // Adapts `callback` for use in a context which is expecting a callback with
122 // additional parameters. Returns a null callback if `callback` is null.
123 //
124 // Usage:
125 //   bool LogError(char* error_message) {
126 //     if (error_message) {
127 //       cout << "Log: " << error_message << endl;
128 //       return false;
129 //     }
130 //     return true;
131 //   }
132 //   base::RepeatingCallback<bool(int, char*)> cb =
133 //      base::IgnoreArgs<int>(base::BindRepeating(&LogError));
134 //   CHECK_EQ(true, cb.Run(42, nullptr));
135 //
136 // Note in the example above that the type(s) passed to `IgnoreArgs`
137 // represent the additional prepended parameters (those which will be
138 // "ignored").
139 template <typename... Preargs, typename... Args, typename R>
140 RepeatingCallback<R(Preargs..., Args...)> IgnoreArgs(
141     RepeatingCallback<R(Args...)> callback) {
142   return callback ? ::base::BindRepeating(
143                         [](RepeatingCallback<R(Args...)> callback, Preargs...,
144                            Args... args) {
145                           return std::move(callback).Run(
146                               std::forward<Args>(args)...);
147                         },
148                         std::move(callback))
149                   : RepeatingCallback<R(Preargs..., Args...)>();
150 }
151 
152 // As above, but for OnceCallback.
153 template <typename... Preargs, typename... Args, typename R>
154 OnceCallback<R(Preargs..., Args...)> IgnoreArgs(
155     OnceCallback<R(Args...)> callback) {
156   return callback ? ::base::BindOnce(
157                         [](OnceCallback<R(Args...)> callback, Preargs...,
158                            Args... args) {
159                           return std::move(callback).Run(
160                               std::forward<Args>(args)...);
161                         },
162                         std::move(callback))
163                   : OnceCallback<R(Preargs..., Args...)>();
164 }
165 
166 // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
167 // that the Closure is executed no matter how the current scope exits.
168 // If you are looking for "ScopedCallback", "CallbackRunner", or
169 // "CallbackScoper" this is the class you want.
170 class BASE_EXPORT ScopedClosureRunner {
171  public:
172   ScopedClosureRunner();
173   [[nodiscard]] explicit ScopedClosureRunner(OnceClosure closure);
174   ScopedClosureRunner(ScopedClosureRunner&& other);
175   // Runs the current closure if it's set, then replaces it with the closure
176   // from |other|. This is akin to how unique_ptr frees the contained pointer in
177   // its move assignment operator. If you need to explicitly avoid running any
178   // current closure, use ReplaceClosure().
179   ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
180   ~ScopedClosureRunner();
181 
182   explicit operator bool() const { return !!closure_; }
183 
184   // Calls the current closure and resets it, so it wont be called again.
185   void RunAndReset();
186 
187   // Replaces closure with the new one releasing the old one without calling it.
188   void ReplaceClosure(OnceClosure closure);
189 
190   // Releases the Closure without calling.
191   [[nodiscard]] OnceClosure Release();
192 
193  private:
194   OnceClosure closure_;
195 };
196 
197 // Returns a placeholder type that will implicitly convert into a null callback,
198 // similar to how std::nullopt / std::nullptr work in conjunction with
199 // std::optional and various smart pointer types.
200 constexpr auto NullCallback() {
201   return internal::NullCallbackTag();
202 }
203 
204 // Returns a placeholder type that will implicitly convert into a callback that
205 // does nothing, similar to how std::nullopt / std::nullptr work in conjunction
206 // with std::optional and various smart pointer types.
207 constexpr auto DoNothing() {
208   return internal::DoNothingCallbackTag();
209 }
210 
211 // Similar to the above, but with a type hint. Useful for disambiguating
212 // among multiple function overloads that take callbacks with different
213 // signatures:
214 //
215 // void F(base::OnceCallback<void()> callback);     // 1
216 // void F(base::OnceCallback<void(int)> callback);  // 2
217 //
218 // F(base::NullCallbackAs<void()>());               // calls 1
219 // F(base::DoNothingAs<void(int)>());               // calls 2
220 template <typename Signature>
221 constexpr auto NullCallbackAs() {
222   return internal::NullCallbackTag::WithSignature<Signature>();
223 }
224 
225 template <typename Signature>
226 constexpr auto DoNothingAs() {
227   return internal::DoNothingCallbackTag::WithSignature<Signature>();
228 }
229 
230 // Similar to DoNothing above, but with bound arguments. This helper is useful
231 // for keeping objects alive until the callback runs.
232 // Example:
233 //
234 // void F(base::OnceCallback<void(int)> result_callback);
235 //
236 // std::unique_ptr<MyClass> ptr;
237 // F(base::DoNothingWithBoundArgs(std::move(ptr)));
238 template <typename... Args>
239 constexpr auto DoNothingWithBoundArgs(Args&&... args) {
240   return internal::DoNothingCallbackTag::WithBoundArguments(
241       std::forward<Args>(args)...);
242 }
243 
244 // Creates a callback that returns `value` when invoked. This helper is useful
245 // for implementing factories that return a constant value.
246 // Example:
247 //
248 // void F(base::OnceCallback<Widget()> factory);
249 //
250 // Widget widget = ...;
251 // F(base::ReturnValueOnce(std::move(widget)));
252 template <typename T>
253 constexpr OnceCallback<T(void)> ReturnValueOnce(T value) {
254   static_assert(!std::is_reference_v<T>);
255   return base::BindOnce([](T value) { return value; }, std::move(value));
256 }
257 
258 // Useful for creating a Closure that will delete a pointer when invoked. Only
259 // use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
260 // fit.
261 template <typename T>
262 void DeletePointer(T* obj) {
263   delete obj;
264 }
265 
266 #if __OBJC__
267 
268 // Creates an Objective-C block with the same signature as the corresponding
269 // callback. Can be used to implement a callback based API internally based
270 // on a block based Objective-C API.
271 //
272 // Overloaded to work with both repeating and one shot callbacks. Calling the
273 // block wrapping a base::OnceCallback<...> multiple times will crash (there
274 // is no way to mark the block as callable only once). Only use that when you
275 // know that Objective-C API will only invoke the block once.
276 template <typename R, typename... Args>
277 auto CallbackToBlock(base::OnceCallback<R(Args...)> callback) {
278   __block base::OnceCallback<R(Args...)> block_callback = std::move(callback);
279   return ^(Args... args) {
280     return std::move(block_callback).Run(std::forward<Args>(args)...);
281   };
282 }
283 
284 template <typename R, typename... Args>
285 auto CallbackToBlock(base::RepeatingCallback<R(Args...)> callback) {
286   return ^(Args... args) {
287     return callback.Run(std::forward<Args>(args)...);
288   };
289 }
290 
291 #endif  // __OBJC__
292 
293 }  // namespace base
294 
295 #endif  // BASE_FUNCTIONAL_CALLBACK_HELPERS_H_
296