// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This defines helpful methods for dealing with Callbacks. Because Callbacks // are implemented using templates, with a class per callback signature, adding // methods to Callback<> itself is unattractive (lots of extra code gets // generated). Instead, consider adding methods here. #ifndef BASE_FUNCTIONAL_CALLBACK_HELPERS_H_ #define BASE_FUNCTIONAL_CALLBACK_HELPERS_H_ #include <atomic> #include <memory> #include <ostream> #include <type_traits> #include <utility> #include "base/atomicops.h" #include "base/base_export.h" #include "base/check.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_tags.h" namespace base { namespace internal { template <typename T> struct IsBaseCallbackImpl : std::false_type { … }; IsBaseCallbackImpl<OnceCallback<R (Args...)>>; IsBaseCallbackImpl<RepeatingCallback<R (Args...)>>; } // namespace internal // IsBaseCallback<T> is satisfied if and only if T is an instantiation of // base::OnceCallback<Signature> or base::RepeatingCallback<Signature>. IsBaseCallback; namespace internal { template <typename... Args> class OnceCallbackHolder final { … }; template <typename... Args> void ForwardRepeatingCallbacksImpl( std::vector<RepeatingCallback<void(Args...)>> cbs, Args... args) { … } } // namespace internal // Wraps the given RepeatingCallbacks and return one RepeatingCallbacks with an // identical signature. On invocation of this callback, all the given // RepeatingCallbacks will be called with the same arguments. Unbound arguments // must be copyable. template <typename... Args> RepeatingCallback<void(Args...)> ForwardRepeatingCallbacks( std::initializer_list<RepeatingCallback<void(Args...)>>&& cbs) { … } // Wraps the given OnceCallback and returns two OnceCallbacks with an identical // signature. On first invokation of either returned callbacks, the original // callback is invoked. Invoking the remaining callback results in a crash. template <typename... Args> std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>> SplitOnceCallback(OnceCallback<void(Args...)> callback) { … } // Adapts `callback` for use in a context which is expecting a callback with // additional parameters. Returns a null callback if `callback` is null. // // Usage: // bool LogError(char* error_message) { // if (error_message) { // cout << "Log: " << error_message << endl; // return false; // } // return true; // } // base::RepeatingCallback<bool(int, char*)> cb = // base::IgnoreArgs<int>(base::BindRepeating(&LogError)); // CHECK_EQ(true, cb.Run(42, nullptr)); // // Note in the example above that the type(s) passed to `IgnoreArgs` // represent the additional prepended parameters (those which will be // "ignored"). template <typename... Preargs, typename... Args, typename R> RepeatingCallback<R(Preargs..., Args...)> IgnoreArgs( RepeatingCallback<R(Args...)> callback) { … } // As above, but for OnceCallback. template <typename... Preargs, typename... Args, typename R> OnceCallback<R(Preargs..., Args...)> IgnoreArgs( OnceCallback<R(Args...)> callback) { … } // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures // that the Closure is executed no matter how the current scope exits. // If you are looking for "ScopedCallback", "CallbackRunner", or // "CallbackScoper" this is the class you want. class BASE_EXPORT ScopedClosureRunner { … }; // Returns a placeholder type that will implicitly convert into a null callback, // similar to how std::nullopt / std::nullptr work in conjunction with // std::optional and various smart pointer types. constexpr auto NullCallback() { … } // Returns a placeholder type that will implicitly convert into a callback that // does nothing, similar to how std::nullopt / std::nullptr work in conjunction // with std::optional and various smart pointer types. constexpr auto DoNothing() { … } // Similar to the above, but with a type hint. Useful for disambiguating // among multiple function overloads that take callbacks with different // signatures: // // void F(base::OnceCallback<void()> callback); // 1 // void F(base::OnceCallback<void(int)> callback); // 2 // // F(base::NullCallbackAs<void()>()); // calls 1 // F(base::DoNothingAs<void(int)>()); // calls 2 template <typename Signature> constexpr auto NullCallbackAs() { … } template <typename Signature> constexpr auto DoNothingAs() { … } // Similar to DoNothing above, but with bound arguments. This helper is useful // for keeping objects alive until the callback runs. // Example: // // void F(base::OnceCallback<void(int)> result_callback); // // std::unique_ptr<MyClass> ptr; // F(base::DoNothingWithBoundArgs(std::move(ptr))); template <typename... Args> constexpr auto DoNothingWithBoundArgs(Args&&... args) { … } // Creates a callback that returns `value` when invoked. This helper is useful // for implementing factories that return a constant value. // Example: // // void F(base::OnceCallback<Widget()> factory); // // Widget widget = ...; // F(base::ReturnValueOnce(std::move(widget))); template <typename T> constexpr OnceCallback<T(void)> ReturnValueOnce(T value) { … } // Useful for creating a Closure that will delete a pointer when invoked. Only // use this when necessary. In most cases MessageLoop::DeleteSoon() is a better // fit. template <typename T> void DeletePointer(T* obj) { … } #if __OBJC__ // Creates an Objective-C block with the same signature as the corresponding // callback. Can be used to implement a callback based API internally based // on a block based Objective-C API. // // Overloaded to work with both repeating and one shot callbacks. Calling the // block wrapping a base::OnceCallback<...> multiple times will crash (there // is no way to mark the block as callable only once). Only use that when you // know that Objective-C API will only invoke the block once. template <typename R, typename... Args> auto CallbackToBlock(base::OnceCallback<R(Args...)> callback) { __block base::OnceCallback<R(Args...)> block_callback = std::move(callback); return ^(Args... args) { return std::move(block_callback).Run(std::forward<Args>(args)...); }; } template <typename R, typename... Args> auto CallbackToBlock(base::RepeatingCallback<R(Args...)> callback) { return ^(Args... args) { return callback.Run(std::forward<Args>(args)...); }; } #endif // __OBJC__ } // namespace base #endif // BASE_FUNCTIONAL_CALLBACK_HELPERS_H_