callback_helpers.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 <type_traits>
  11. #include <utility>
  12. #include "base/atomicops.h"
  13. #include "base/bind.h"
  14. #include "base/callback.h"
  15. #include "base/compiler_specific.h"
  16. #include "base/macros.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. void Run(Args... args) {
  59. if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
  60. return;
  61. DCHECK(callback_);
  62. std::move(callback_).Run(std::forward<Args>(args)...);
  63. }
  64. private:
  65. volatile subtle::Atomic32 has_run_ = 0;
  66. base::OnceCallback<void(Args...)> callback_;
  67. DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper);
  68. };
  69. } // namespace internal
  70. // Wraps the given OnceCallback into a RepeatingCallback that relays its
  71. // invocation to the original OnceCallback on the first invocation. The
  72. // following invocations are just ignored.
  73. //
  74. // Note that this deliberately subverts the Once/Repeating paradigm of Callbacks
  75. // but helps ease the migration from old-style Callbacks. Avoid if possible; use
  76. // if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593
  77. template <typename... Args>
  78. RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
  79. OnceCallback<void(Args...)> callback) {
  80. using Helper = internal::AdaptCallbackForRepeatingHelper<Args...>;
  81. return base::BindRepeating(&Helper::Run,
  82. std::make_unique<Helper>(std::move(callback)));
  83. }
  84. // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
  85. // that the Closure is executed no matter how the current scope exits.
  86. // If you are looking for "ScopedCallback", "CallbackRunner", or
  87. // "CallbackScoper" this is the class you want.
  88. class BASE_EXPORT ScopedClosureRunner {
  89. public:
  90. ScopedClosureRunner();
  91. explicit ScopedClosureRunner(OnceClosure closure);
  92. ~ScopedClosureRunner();
  93. ScopedClosureRunner(ScopedClosureRunner&& other);
  94. // Releases the current closure if it's set and replaces it with the closure
  95. // from |other|.
  96. ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
  97. // Calls the current closure and resets it, so it wont be called again.
  98. void RunAndReset();
  99. // Replaces closure with the new one releasing the old one without calling it.
  100. void ReplaceClosure(OnceClosure closure);
  101. // Releases the Closure without calling.
  102. OnceClosure Release() WARN_UNUSED_RESULT;
  103. private:
  104. OnceClosure closure_;
  105. DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner);
  106. };
  107. } // namespace base
  108. #endif // BASE_CALLBACK_HELPERS_H_