blob: 34ca10fb76b6aaec230874cc8873f23a63446368 [file] [log] [blame]
Daniel Chengcd23b8b2022-09-16 17:16:241// 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
Kevin Lin1e19bc32023-03-30 16:36:2413#include <atomic>
Daniel Chengcd23b8b2022-09-16 17:16:2414#include <memory>
15#include <ostream>
16#include <type_traits>
17#include <utility>
18
Daniel Chengcd23b8b2022-09-16 17:16:2419#include "base/base_export.h"
20#include "base/check.h"
21#include "base/functional/bind.h"
22#include "base/functional/callback.h"
Paul Semel4c1e3e82022-10-24 09:20:5423#include "base/functional/callback_tags.h"
Daniel Chengcd23b8b2022-09-16 17:16:2424
25namespace base {
26
27namespace internal {
28
Daniel Chengcd23b8b2022-09-16 17:16:2429template <typename... Args>
30class OnceCallbackHolder final {
31 public:
32 OnceCallbackHolder(OnceCallback<void(Args...)> callback,
33 bool ignore_extra_runs)
34 : callback_(std::move(callback)), ignore_extra_runs_(ignore_extra_runs) {
35 DCHECK(callback_);
36 }
37 OnceCallbackHolder(const OnceCallbackHolder&) = delete;
38 OnceCallbackHolder& operator=(const OnceCallbackHolder&) = delete;
39
40 void Run(Args... args) {
Venkatesh Srinivas99db1f92023-03-19 06:33:0741 if (has_run_.exchange(true, std::memory_order_relaxed)) {
Daniel Chengcd23b8b2022-09-16 17:16:2442 CHECK(ignore_extra_runs_) << "Both OnceCallbacks returned by "
43 "base::SplitOnceCallback() were run. "
44 "At most one of the pair should be run.";
45 return;
46 }
47 DCHECK(callback_);
48 std::move(callback_).Run(std::forward<Args>(args)...);
49 }
50
51 private:
Kevin Lin1e19bc32023-03-30 16:36:2452 std::atomic<bool> has_run_{false};
Daniel Chengcd23b8b2022-09-16 17:16:2453 base::OnceCallback<void(Args...)> callback_;
54 const bool ignore_extra_runs_;
55};
56
Paul Semel1aba4152023-09-28 16:46:1357template <typename... Args>
58void ForwardRepeatingCallbacksImpl(
59 std::vector<RepeatingCallback<void(Args...)>> cbs,
60 Args... args) {
61 for (auto& cb : cbs) {
62 if (cb) {
63 cb.Run(std::forward<Args>(args)...);
64 }
65 }
66}
67
Daniel Chengcd23b8b2022-09-16 17:16:2468} // namespace internal
69
Paul Semel1aba4152023-09-28 16:46:1370// Wraps the given RepeatingCallbacks and return one RepeatingCallbacks with an
71// identical signature. On invocation of this callback, all the given
72// RepeatingCallbacks will be called with the same arguments. Unbound arguments
73// must be copyable.
74template <typename... Args>
75RepeatingCallback<void(Args...)> ForwardRepeatingCallbacks(
76 std::initializer_list<RepeatingCallback<void(Args...)>>&& cbs) {
77 std::vector<RepeatingCallback<void(Args...)>> v(
78 std::forward<std::initializer_list<RepeatingCallback<void(Args...)>>>(
79 cbs));
80 return BindRepeating(&internal::ForwardRepeatingCallbacksImpl<Args...>,
81 std::move(v));
82}
83
Daniel Chengcd23b8b2022-09-16 17:16:2484// Wraps the given OnceCallback and returns two OnceCallbacks with an identical
85// signature. On first invokation of either returned callbacks, the original
86// callback is invoked. Invoking the remaining callback results in a crash.
87template <typename... Args>
88std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
89SplitOnceCallback(OnceCallback<void(Args...)> callback) {
90 if (!callback) {
91 // Empty input begets two empty outputs.
92 return std::make_pair(OnceCallback<void(Args...)>(),
93 OnceCallback<void(Args...)>());
94 }
95 using Helper = internal::OnceCallbackHolder<Args...>;
96 auto wrapped_once = base::BindRepeating(
97 &Helper::Run, std::make_unique<Helper>(std::move(callback),
98 /*ignore_extra_runs=*/false));
99 return std::make_pair(wrapped_once, wrapped_once);
100}
101
Evan Stade5df74692023-10-02 23:15:57102// Adapts `callback` for use in a context which is expecting a callback with
103// additional parameters. Returns a null callback if `callback` is null.
104//
105// Usage:
Keren Zhu9cd105c82024-08-03 00:00:12106// bool LogError(char* error_message) {
Evan Stade5df74692023-10-02 23:15:57107// if (error_message) {
108// cout << "Log: " << error_message << endl;
Keren Zhu9cd105c82024-08-03 00:00:12109// return false;
Evan Stade5df74692023-10-02 23:15:57110// }
Keren Zhu9cd105c82024-08-03 00:00:12111// return true;
Evan Stade5df74692023-10-02 23:15:57112// }
Keren Zhu9cd105c82024-08-03 00:00:12113// base::RepeatingCallback<bool(int, char*)> cb =
Evan Stade5df74692023-10-02 23:15:57114// base::IgnoreArgs<int>(base::BindRepeating(&LogError));
Keren Zhu9cd105c82024-08-03 00:00:12115// CHECK_EQ(true, cb.Run(42, nullptr));
Evan Stade5df74692023-10-02 23:15:57116//
117// Note in the example above that the type(s) passed to `IgnoreArgs`
118// represent the additional prepended parameters (those which will be
119// "ignored").
Keren Zhu9cd105c82024-08-03 00:00:12120template <typename... Preargs, typename... Args, typename R>
121RepeatingCallback<R(Preargs..., Args...)> IgnoreArgs(
122 RepeatingCallback<R(Args...)> callback) {
L. David Baronca7056e2024-01-11 21:59:43123 return callback ? ::base::BindRepeating(
Keren Zhu9cd105c82024-08-03 00:00:12124 [](RepeatingCallback<R(Args...)> callback, Preargs...,
125 Args... args) {
126 return std::move(callback).Run(
127 std::forward<Args>(args)...);
Evan Stade5df74692023-10-02 23:15:57128 },
129 std::move(callback))
Keren Zhu9cd105c82024-08-03 00:00:12130 : RepeatingCallback<R(Preargs..., Args...)>();
Nicolas Dossou-Gbete51290c2f2022-10-19 12:50:34131}
132
Evan Stade5df74692023-10-02 23:15:57133// As above, but for OnceCallback.
Keren Zhu9cd105c82024-08-03 00:00:12134template <typename... Preargs, typename... Args, typename R>
135OnceCallback<R(Preargs..., Args...)> IgnoreArgs(
136 OnceCallback<R(Args...)> callback) {
L. David Baronca7056e2024-01-11 21:59:43137 return callback ? ::base::BindOnce(
Keren Zhu9cd105c82024-08-03 00:00:12138 [](OnceCallback<R(Args...)> callback, Preargs...,
Evan Stade5df74692023-10-02 23:15:57139 Args... args) {
Keren Zhu9cd105c82024-08-03 00:00:12140 return std::move(callback).Run(
141 std::forward<Args>(args)...);
Evan Stade5df74692023-10-02 23:15:57142 },
143 std::move(callback))
Keren Zhu9cd105c82024-08-03 00:00:12144 : OnceCallback<R(Preargs..., Args...)>();
Nicolas Dossou-Gbete51290c2f2022-10-19 12:50:34145}
146
Daniel Chengcd23b8b2022-09-16 17:16:24147// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
148// that the Closure is executed no matter how the current scope exits.
149// If you are looking for "ScopedCallback", "CallbackRunner", or
150// "CallbackScoper" this is the class you want.
151class BASE_EXPORT ScopedClosureRunner {
152 public:
153 ScopedClosureRunner();
Ian Vollickcf2a3862024-07-11 21:00:37154 [[nodiscard]] explicit ScopedClosureRunner(OnceClosure closure);
Daniel Chengcd23b8b2022-09-16 17:16:24155 ScopedClosureRunner(ScopedClosureRunner&& other);
156 // Runs the current closure if it's set, then replaces it with the closure
157 // from |other|. This is akin to how unique_ptr frees the contained pointer in
158 // its move assignment operator. If you need to explicitly avoid running any
159 // current closure, use ReplaceClosure().
160 ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
161 ~ScopedClosureRunner();
162
163 explicit operator bool() const { return !!closure_; }
164
165 // Calls the current closure and resets it, so it wont be called again.
166 void RunAndReset();
167
168 // Replaces closure with the new one releasing the old one without calling it.
169 void ReplaceClosure(OnceClosure closure);
170
171 // Releases the Closure without calling.
172 [[nodiscard]] OnceClosure Release();
173
174 private:
175 OnceClosure closure_;
176};
177
178// Returns a placeholder type that will implicitly convert into a null callback,
Arthur Sonzognie5fff99c2024-02-21 15:58:24179// similar to how std::nullopt / std::nullptr work in conjunction with
180// std::optional and various smart pointer types.
Daniel Chengcd23b8b2022-09-16 17:16:24181constexpr auto NullCallback() {
182 return internal::NullCallbackTag();
183}
184
185// Returns a placeholder type that will implicitly convert into a callback that
Arthur Sonzognie5fff99c2024-02-21 15:58:24186// does nothing, similar to how std::nullopt / std::nullptr work in conjunction
187// with std::optional and various smart pointer types.
Daniel Chengcd23b8b2022-09-16 17:16:24188constexpr auto DoNothing() {
189 return internal::DoNothingCallbackTag();
190}
191
192// Similar to the above, but with a type hint. Useful for disambiguating
193// among multiple function overloads that take callbacks with different
194// signatures:
195//
196// void F(base::OnceCallback<void()> callback); // 1
197// void F(base::OnceCallback<void(int)> callback); // 2
198//
199// F(base::NullCallbackAs<void()>()); // calls 1
200// F(base::DoNothingAs<void(int)>()); // calls 2
201template <typename Signature>
202constexpr auto NullCallbackAs() {
203 return internal::NullCallbackTag::WithSignature<Signature>();
204}
205
206template <typename Signature>
207constexpr auto DoNothingAs() {
208 return internal::DoNothingCallbackTag::WithSignature<Signature>();
209}
210
Paul Semel4c1e3e82022-10-24 09:20:54211// Similar to DoNothing above, but with bound arguments. This helper is useful
212// for keeping objects alive until the callback runs.
213// Example:
214//
215// void F(base::OnceCallback<void(int)> result_callback);
216//
217// std::unique_ptr<MyClass> ptr;
218// F(base::DoNothingWithBoundArgs(std::move(ptr)));
219template <typename... Args>
220constexpr auto DoNothingWithBoundArgs(Args&&... args) {
221 return internal::DoNothingCallbackTag::WithBoundArguments(
222 std::forward<Args>(args)...);
223}
224
Sylvain Defresneb5363df2023-10-30 19:44:29225// Creates a callback that returns `value` when invoked. This helper is useful
226// for implementing factories that return a constant value.
227// Example:
228//
229// void F(base::OnceCallback<Widget()> factory);
230//
231// Widget widget = ...;
232// F(base::ReturnValueOnce(std::move(widget)));
233template <typename T>
234constexpr OnceCallback<T(void)> ReturnValueOnce(T value) {
235 static_assert(!std::is_reference_v<T>);
236 return base::BindOnce([](T value) { return value; }, std::move(value));
237}
238
Daniel Chengcd23b8b2022-09-16 17:16:24239// Useful for creating a Closure that will delete a pointer when invoked. Only
240// use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
241// fit.
242template <typename T>
243void DeletePointer(T* obj) {
244 delete obj;
245}
246
Sylvain Defresne953d5392023-07-20 11:01:37247#if __OBJC__
248
249// Creates an Objective-C block with the same signature as the corresponding
250// callback. Can be used to implement a callback based API internally based
251// on a block based Objective-C API.
252//
253// Overloaded to work with both repeating and one shot callbacks. Calling the
254// block wrapping a base::OnceCallback<...> multiple times will crash (there
255// is no way to mark the block as callable only once). Only use that when you
256// know that Objective-C API will only invoke the block once.
257template <typename R, typename... Args>
258auto CallbackToBlock(base::OnceCallback<R(Args...)> callback) {
259 __block base::OnceCallback<R(Args...)> block_callback = std::move(callback);
260 return ^(Args... args) {
261 return std::move(block_callback).Run(std::forward<Args>(args)...);
262 };
263}
264
265template <typename R, typename... Args>
266auto CallbackToBlock(base::RepeatingCallback<R(Args...)> callback) {
267 return ^(Args... args) {
268 return callback.Run(std::forward<Args>(args)...);
269 };
270}
271
272#endif // __OBJC__
273
Daniel Chengcd23b8b2022-09-16 17:16:24274} // namespace base
275
276#endif // BASE_FUNCTIONAL_CALLBACK_HELPERS_H_