tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

callback_helpers.h (11378B)


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