xref: /aosp_15_r20/external/cronet/base/functional/callback_helpers.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 //   void LogError(char* error_message) {
126 //     if (error_message) {
127 //       cout << "Log: " << error_message << endl;
128 //     }
129 //   }
130 //   base::RepeatingCallback<void(int, char*)> cb =
131 //      base::IgnoreArgs<int>(base::BindRepeating(&LogError));
132 //   cb.Run(42, nullptr);
133 //
134 // Note in the example above that the type(s) passed to `IgnoreArgs`
135 // represent the additional prepended parameters (those which will be
136 // "ignored").
137 template <typename... Preargs, typename... Args>
138 RepeatingCallback<void(Preargs..., Args...)> IgnoreArgs(
139     RepeatingCallback<void(Args...)> callback) {
140   return callback ? ::base::BindRepeating(
141                         [](RepeatingCallback<void(Args...)> callback,
142                            Preargs..., Args... args) {
143                           std::move(callback).Run(std::forward<Args>(args)...);
144                         },
145                         std::move(callback))
146                   : RepeatingCallback<void(Preargs..., Args...)>();
147 }
148 
149 // As above, but for OnceCallback.
150 template <typename... Preargs, typename... Args>
151 OnceCallback<void(Preargs..., Args...)> IgnoreArgs(
152     OnceCallback<void(Args...)> callback) {
153   return callback ? ::base::BindOnce(
154                         [](OnceCallback<void(Args...)> callback, Preargs...,
155                            Args... args) {
156                           std::move(callback).Run(std::forward<Args>(args)...);
157                         },
158                         std::move(callback))
159                   : OnceCallback<void(Preargs..., Args...)>();
160 }
161 
162 // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
163 // that the Closure is executed no matter how the current scope exits.
164 // If you are looking for "ScopedCallback", "CallbackRunner", or
165 // "CallbackScoper" this is the class you want.
166 class BASE_EXPORT ScopedClosureRunner {
167  public:
168   ScopedClosureRunner();
169   explicit ScopedClosureRunner(OnceClosure closure);
170   ScopedClosureRunner(ScopedClosureRunner&& other);
171   // Runs the current closure if it's set, then replaces it with the closure
172   // from |other|. This is akin to how unique_ptr frees the contained pointer in
173   // its move assignment operator. If you need to explicitly avoid running any
174   // current closure, use ReplaceClosure().
175   ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
176   ~ScopedClosureRunner();
177 
178   explicit operator bool() const { return !!closure_; }
179 
180   // Calls the current closure and resets it, so it wont be called again.
181   void RunAndReset();
182 
183   // Replaces closure with the new one releasing the old one without calling it.
184   void ReplaceClosure(OnceClosure closure);
185 
186   // Releases the Closure without calling.
187   [[nodiscard]] OnceClosure Release();
188 
189  private:
190   OnceClosure closure_;
191 };
192 
193 // Returns a placeholder type that will implicitly convert into a null callback,
194 // similar to how std::nullopt / std::nullptr work in conjunction with
195 // std::optional and various smart pointer types.
196 constexpr auto NullCallback() {
197   return internal::NullCallbackTag();
198 }
199 
200 // Returns a placeholder type that will implicitly convert into a callback that
201 // does nothing, similar to how std::nullopt / std::nullptr work in conjunction
202 // with std::optional and various smart pointer types.
203 constexpr auto DoNothing() {
204   return internal::DoNothingCallbackTag();
205 }
206 
207 // Similar to the above, but with a type hint. Useful for disambiguating
208 // among multiple function overloads that take callbacks with different
209 // signatures:
210 //
211 // void F(base::OnceCallback<void()> callback);     // 1
212 // void F(base::OnceCallback<void(int)> callback);  // 2
213 //
214 // F(base::NullCallbackAs<void()>());               // calls 1
215 // F(base::DoNothingAs<void(int)>());               // calls 2
216 template <typename Signature>
217 constexpr auto NullCallbackAs() {
218   return internal::NullCallbackTag::WithSignature<Signature>();
219 }
220 
221 template <typename Signature>
222 constexpr auto DoNothingAs() {
223   return internal::DoNothingCallbackTag::WithSignature<Signature>();
224 }
225 
226 // Similar to DoNothing above, but with bound arguments. This helper is useful
227 // for keeping objects alive until the callback runs.
228 // Example:
229 //
230 // void F(base::OnceCallback<void(int)> result_callback);
231 //
232 // std::unique_ptr<MyClass> ptr;
233 // F(base::DoNothingWithBoundArgs(std::move(ptr)));
234 template <typename... Args>
235 constexpr auto DoNothingWithBoundArgs(Args&&... args) {
236   return internal::DoNothingCallbackTag::WithBoundArguments(
237       std::forward<Args>(args)...);
238 }
239 
240 // Creates a callback that returns `value` when invoked. This helper is useful
241 // for implementing factories that return a constant value.
242 // Example:
243 //
244 // void F(base::OnceCallback<Widget()> factory);
245 //
246 // Widget widget = ...;
247 // F(base::ReturnValueOnce(std::move(widget)));
248 template <typename T>
249 constexpr OnceCallback<T(void)> ReturnValueOnce(T value) {
250   static_assert(!std::is_reference_v<T>);
251   return base::BindOnce([](T value) { return value; }, std::move(value));
252 }
253 
254 // Useful for creating a Closure that will delete a pointer when invoked. Only
255 // use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
256 // fit.
257 template <typename T>
258 void DeletePointer(T* obj) {
259   delete obj;
260 }
261 
262 #if __OBJC__
263 
264 // Creates an Objective-C block with the same signature as the corresponding
265 // callback. Can be used to implement a callback based API internally based
266 // on a block based Objective-C API.
267 //
268 // Overloaded to work with both repeating and one shot callbacks. Calling the
269 // block wrapping a base::OnceCallback<...> multiple times will crash (there
270 // is no way to mark the block as callable only once). Only use that when you
271 // know that Objective-C API will only invoke the block once.
272 template <typename R, typename... Args>
273 auto CallbackToBlock(base::OnceCallback<R(Args...)> callback) {
274   __block base::OnceCallback<R(Args...)> block_callback = std::move(callback);
275   return ^(Args... args) {
276     return std::move(block_callback).Run(std::forward<Args>(args)...);
277   };
278 }
279 
280 template <typename R, typename... Args>
281 auto CallbackToBlock(base::RepeatingCallback<R(Args...)> callback) {
282   return ^(Args... args) {
283     return callback.Run(std::forward<Args>(args)...);
284   };
285 }
286 
287 #endif  // __OBJC__
288 
289 }  // namespace base
290 
291 #endif  // BASE_FUNCTIONAL_CALLBACK_HELPERS_H_
292