callback_helpers.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // This defines helpful methods for dealing with Callbacks. Because Callbacks
  5. // are implemented using templates, with a class per callback signature, adding
  6. // methods to Callback<> itself is unattractive (lots of extra code gets
  7. // generated). Instead, consider adding methods here.
  8. #ifndef BASE_CALLBACK_HELPERS_H_
  9. #define BASE_CALLBACK_HELPERS_H_
  10. #include <memory>
  11. #include <type_traits>
  12. #include <utility>
  13. #include "base/atomicops.h"
  14. #include "base/bind.h"
  15. #include "base/callback.h"
  16. #include "base/compiler_specific.h"
  17. #include "base/memory/ptr_util.h"
  18. namespace base {
  19. namespace internal {
  20. template <typename T>
  21. struct IsBaseCallbackImpl : std::false_type {};
  22. template <typename R, typename... Args>
  23. struct IsBaseCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
  24. template <typename R, typename... Args>
  25. struct IsBaseCallbackImpl<RepeatingCallback<R(Args...)>> : std::true_type {};
  26. template <typename T>
  27. struct IsOnceCallbackImpl : std::false_type {};
  28. template <typename R, typename... Args>
  29. struct IsOnceCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
  30. } // namespace internal
  31. // IsBaseCallback<T>::value is true when T is any of the Closure or Callback
  32. // family of types.
  33. template <typename T>
  34. using IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>;
  35. // IsOnceCallback<T>::value is true when T is a OnceClosure or OnceCallback
  36. // type.
  37. template <typename T>
  38. using IsOnceCallback = internal::IsOnceCallbackImpl<std::decay_t<T>>;
  39. // SFINAE friendly enabler allowing to overload methods for both Repeating and
  40. // OnceCallbacks.
  41. //
  42. // Usage:
  43. // template <template <typename> class CallbackType,
  44. // ... other template args ...,
  45. // typename = EnableIfIsBaseCallback<CallbackType>>
  46. // void DoStuff(CallbackType<...> cb, ...);
  47. template <template <typename> class CallbackType>
  48. using EnableIfIsBaseCallback =
  49. std::enable_if_t<IsBaseCallback<CallbackType<void()>>::value>;
  50. namespace internal {
  51. template <typename... Args>
  52. class AdaptCallbackForRepeatingHelper final {
  53. public:
  54. explicit AdaptCallbackForRepeatingHelper(OnceCallback<void(Args...)> callback)
  55. : callback_(std::move(callback)) {
  56. DCHECK(callback_);
  57. }
  58. AdaptCallbackForRepeatingHelper(const AdaptCallbackForRepeatingHelper&) =
  59. delete;
  60. AdaptCallbackForRepeatingHelper& operator=(
  61. const AdaptCallbackForRepeatingHelper&) = delete;
  62. void Run(Args... args) {
  63. if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
  64. return;
  65. DCHECK(callback_);
  66. std::move(callback_).Run(std::forward<Args>(args)...);
  67. }
  68. private:
  69. volatile subtle::Atomic32 has_run_ = 0;
  70. base::OnceCallback<void(Args...)> callback_;
  71. };
  72. } // namespace internal
  73. // Wraps the given OnceCallback into a RepeatingCallback that relays its
  74. // invocation to the original OnceCallback on the first invocation. The
  75. // following invocations are just ignored.
  76. //
  77. // Note that this deliberately subverts the Once/Repeating paradigm of Callbacks
  78. // but helps ease the migration from old-style Callbacks. Avoid if possible; use
  79. // if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593
  80. template <typename... Args>
  81. RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
  82. OnceCallback<void(Args...)> callback) {
  83. using Helper = internal::AdaptCallbackForRepeatingHelper<Args...>;
  84. return base::BindRepeating(&Helper::Run,
  85. std::make_unique<Helper>(std::move(callback)));
  86. }
  87. // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
  88. // that the Closure is executed no matter how the current scope exits.
  89. // If you are looking for "ScopedCallback", "CallbackRunner", or
  90. // "CallbackScoper" this is the class you want.
  91. class BASE_EXPORT ScopedClosureRunner {
  92. public:
  93. ScopedClosureRunner();
  94. explicit ScopedClosureRunner(OnceClosure closure);
  95. ScopedClosureRunner(const ScopedClosureRunner&) = delete;
  96. ScopedClosureRunner& operator=(const ScopedClosureRunner&) = delete;
  97. ~ScopedClosureRunner();
  98. ScopedClosureRunner(ScopedClosureRunner&& other);
  99. // Releases the current closure if it's set and replaces it with the closure
  100. // from |other|.
  101. ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
  102. // Calls the current closure and resets it, so it wont be called again.
  103. void RunAndReset();
  104. // Replaces closure with the new one releasing the old one without calling it.
  105. void ReplaceClosure(OnceClosure closure);
  106. // Releases the Closure without calling.
  107. OnceClosure Release() WARN_UNUSED_RESULT;
  108. private:
  109. OnceClosure closure_;
  110. };
  111. } // namespace base
  112. #endif // BASE_CALLBACK_HELPERS_H_