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