callback_internal.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 file contains utility functions and classes that help the
  5. // implementation, and management of the Callback objects.
  6. #ifndef BASE_CALLBACK_INTERNAL_H_
  7. #define BASE_CALLBACK_INTERNAL_H_
  8. #include <utility>
  9. #include "base/base_export.h"
  10. #include "base/callback_forward.h"
  11. #include "base/memory/ref_counted.h"
  12. namespace base {
  13. struct FakeBindState;
  14. namespace internal {
  15. class BindStateBase;
  16. class FinallyExecutorCommon;
  17. class ThenAndCatchExecutorCommon;
  18. template <typename ReturnType>
  19. class PostTaskExecutor;
  20. template <typename Functor, typename... BoundArgs>
  21. struct BindState;
  22. class CallbackBase;
  23. class CallbackBaseCopyable;
  24. struct BindStateBaseRefCountTraits {
  25. static void Destruct(const BindStateBase*);
  26. };
  27. template <typename T>
  28. using PassingType = std::conditional_t<std::is_scalar_v<T>, T, T&&>;
  29. // BindStateBase is used to provide an opaque handle that the Callback
  30. // class can use to represent a function object with bound arguments. It
  31. // behaves as an existential type that is used by a corresponding
  32. // DoInvoke function to perform the function execution. This allows
  33. // us to shield the Callback class from the types of the bound argument via
  34. // "type erasure."
  35. // At the base level, the only task is to add reference counting data. Avoid
  36. // using or inheriting any virtual functions. Creating a vtable for every
  37. // BindState template instantiation results in a lot of bloat. Its only task is
  38. // to call the destructor which can be done with a function pointer.
  39. class BASE_EXPORT BindStateBase
  40. : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
  41. public:
  42. REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
  43. enum CancellationQueryMode {
  44. IS_CANCELLED,
  45. MAYBE_VALID,
  46. };
  47. using InvokeFuncStorage = void(*)();
  48. BindStateBase(const BindStateBase&) = delete;
  49. BindStateBase& operator=(const BindStateBase&) = delete;
  50. private:
  51. BindStateBase(InvokeFuncStorage polymorphic_invoke,
  52. void (*destructor)(const BindStateBase*));
  53. BindStateBase(InvokeFuncStorage polymorphic_invoke,
  54. void (*destructor)(const BindStateBase*),
  55. bool (*query_cancellation_traits)(const BindStateBase*,
  56. CancellationQueryMode mode));
  57. ~BindStateBase() = default;
  58. friend struct BindStateBaseRefCountTraits;
  59. friend class RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits>;
  60. friend class CallbackBase;
  61. friend class CallbackBaseCopyable;
  62. // Allowlist subclasses that access the destructor of BindStateBase.
  63. template <typename Functor, typename... BoundArgs>
  64. friend struct BindState;
  65. friend struct ::base::FakeBindState;
  66. bool IsCancelled() const {
  67. return query_cancellation_traits_(this, IS_CANCELLED);
  68. }
  69. bool MaybeValid() const {
  70. return query_cancellation_traits_(this, MAYBE_VALID);
  71. }
  72. // In C++, it is safe to cast function pointers to function pointers of
  73. // another type. It is not okay to use void*. We create a InvokeFuncStorage
  74. // that that can store our function pointer, and then cast it back to
  75. // the original type on usage.
  76. InvokeFuncStorage polymorphic_invoke_;
  77. // Pointer to a function that will properly destroy |this|.
  78. void (*destructor_)(const BindStateBase*);
  79. bool (*query_cancellation_traits_)(const BindStateBase*,
  80. CancellationQueryMode mode);
  81. };
  82. // Holds the Callback methods that don't require specialization to reduce
  83. // template bloat.
  84. // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
  85. // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
  86. class BASE_EXPORT CallbackBase {
  87. public:
  88. inline CallbackBase(CallbackBase&& c) noexcept;
  89. CallbackBase& operator=(CallbackBase&& c) noexcept;
  90. explicit CallbackBase(const CallbackBaseCopyable& c);
  91. CallbackBase& operator=(const CallbackBaseCopyable& c);
  92. explicit CallbackBase(CallbackBaseCopyable&& c) noexcept;
  93. CallbackBase& operator=(CallbackBaseCopyable&& c) noexcept;
  94. // Returns true if Callback is null (doesn't refer to anything).
  95. bool is_null() const { return !bind_state_; }
  96. explicit operator bool() const { return !is_null(); }
  97. // Returns true if the callback invocation will be nop due to an cancellation.
  98. // It's invalid to call this on uninitialized callback.
  99. //
  100. // Must be called on the Callback's destination sequence.
  101. bool IsCancelled() const;
  102. // If this returns false, the callback invocation will be a nop due to a
  103. // cancellation. This may(!) still return true, even on a cancelled callback.
  104. //
  105. // This function is thread-safe.
  106. bool MaybeValid() const;
  107. // Returns the Callback into an uninitialized state.
  108. void Reset();
  109. protected:
  110. friend class FinallyExecutorCommon;
  111. friend class ThenAndCatchExecutorCommon;
  112. template <typename ReturnType>
  113. friend class PostTaskExecutor;
  114. using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
  115. // Returns true if this callback equals |other|. |other| may be null.
  116. bool EqualsInternal(const CallbackBase& other) const;
  117. inline constexpr CallbackBase();
  118. // Allow initializing of |bind_state_| via the constructor to avoid default
  119. // initialization of the scoped_refptr.
  120. explicit inline CallbackBase(BindStateBase* bind_state);
  121. InvokeFuncStorage polymorphic_invoke() const {
  122. return bind_state_->polymorphic_invoke_;
  123. }
  124. // Force the destructor to be instantiated inside this translation unit so
  125. // that our subclasses will not get inlined versions. Avoids more template
  126. // bloat.
  127. ~CallbackBase();
  128. scoped_refptr<BindStateBase> bind_state_;
  129. };
  130. constexpr CallbackBase::CallbackBase() = default;
  131. CallbackBase::CallbackBase(CallbackBase&&) noexcept = default;
  132. CallbackBase::CallbackBase(BindStateBase* bind_state)
  133. : bind_state_(AdoptRef(bind_state)) {}
  134. // CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
  135. class BASE_EXPORT CallbackBaseCopyable : public CallbackBase {
  136. public:
  137. CallbackBaseCopyable(const CallbackBaseCopyable& c);
  138. CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept = default;
  139. CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
  140. CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
  141. protected:
  142. constexpr CallbackBaseCopyable() = default;
  143. explicit CallbackBaseCopyable(BindStateBase* bind_state)
  144. : CallbackBase(bind_state) {}
  145. ~CallbackBaseCopyable() = default;
  146. };
  147. // Helpers for the `Then()` implementation.
  148. template <typename OriginalCallback, typename ThenCallback>
  149. struct ThenHelper;
  150. // Specialization when original callback returns `void`.
  151. template <template <typename> class OriginalCallback,
  152. template <typename>
  153. class ThenCallback,
  154. typename... OriginalArgs,
  155. typename ThenR,
  156. typename... ThenArgs>
  157. struct ThenHelper<OriginalCallback<void(OriginalArgs...)>,
  158. ThenCallback<ThenR(ThenArgs...)>> {
  159. static_assert(sizeof...(ThenArgs) == 0,
  160. "|then| callback cannot accept parameters if |this| has a "
  161. "void return type.");
  162. static auto CreateTrampoline() {
  163. return [](OriginalCallback<void(OriginalArgs...)> c1,
  164. ThenCallback<ThenR(ThenArgs...)> c2, OriginalArgs... c1_args) {
  165. std::move(c1).Run(std::forward<OriginalArgs>(c1_args)...);
  166. return std::move(c2).Run();
  167. };
  168. }
  169. };
  170. // Specialization when original callback returns a non-void type.
  171. template <template <typename> class OriginalCallback,
  172. template <typename>
  173. class ThenCallback,
  174. typename OriginalR,
  175. typename... OriginalArgs,
  176. typename ThenR,
  177. typename... ThenArgs>
  178. struct ThenHelper<OriginalCallback<OriginalR(OriginalArgs...)>,
  179. ThenCallback<ThenR(ThenArgs...)>> {
  180. static_assert(sizeof...(ThenArgs) == 1,
  181. "|then| callback must accept exactly one parameter if |this| "
  182. "has a non-void return type.");
  183. // TODO(dcheng): This should probably check is_convertible as well (same with
  184. // `AssertBindArgsValidity`).
  185. static_assert(std::is_constructible_v<ThenArgs..., OriginalR&&>,
  186. "|then| callback's parameter must be constructible from "
  187. "return type of |this|.");
  188. static auto CreateTrampoline() {
  189. return [](OriginalCallback<OriginalR(OriginalArgs...)> c1,
  190. ThenCallback<ThenR(ThenArgs...)> c2, OriginalArgs... c1_args) {
  191. return std::move(c2).Run(
  192. std::move(c1).Run(std::forward<OriginalArgs>(c1_args)...));
  193. };
  194. }
  195. };
  196. } // namespace internal
  197. } // namespace base
  198. #endif // BASE_CALLBACK_INTERNAL_H_