xref: /aosp_15_r20/external/libchrome/base/callback_internal.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker // This file contains utility functions and classes that help the
6*635a8641SAndroid Build Coastguard Worker // implementation, and management of the Callback objects.
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #ifndef BASE_CALLBACK_INTERNAL_H_
9*635a8641SAndroid Build Coastguard Worker #define BASE_CALLBACK_INTERNAL_H_
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/callback_forward.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
15*635a8641SAndroid Build Coastguard Worker 
16*635a8641SAndroid Build Coastguard Worker namespace base {
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker struct FakeBindState;
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker namespace internal {
21*635a8641SAndroid Build Coastguard Worker 
22*635a8641SAndroid Build Coastguard Worker class CallbackBase;
23*635a8641SAndroid Build Coastguard Worker class CallbackBaseCopyable;
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker class BindStateBase;
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker template <typename Functor, typename... BoundArgs>
28*635a8641SAndroid Build Coastguard Worker struct BindState;
29*635a8641SAndroid Build Coastguard Worker 
30*635a8641SAndroid Build Coastguard Worker struct BindStateBaseRefCountTraits {
31*635a8641SAndroid Build Coastguard Worker   static void Destruct(const BindStateBase*);
32*635a8641SAndroid Build Coastguard Worker };
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker template <typename T>
35*635a8641SAndroid Build Coastguard Worker using PassingType = std::conditional_t<std::is_scalar<T>::value, T, T&&>;
36*635a8641SAndroid Build Coastguard Worker 
37*635a8641SAndroid Build Coastguard Worker // BindStateBase is used to provide an opaque handle that the Callback
38*635a8641SAndroid Build Coastguard Worker // class can use to represent a function object with bound arguments.  It
39*635a8641SAndroid Build Coastguard Worker // behaves as an existential type that is used by a corresponding
40*635a8641SAndroid Build Coastguard Worker // DoInvoke function to perform the function execution.  This allows
41*635a8641SAndroid Build Coastguard Worker // us to shield the Callback class from the types of the bound argument via
42*635a8641SAndroid Build Coastguard Worker // "type erasure."
43*635a8641SAndroid Build Coastguard Worker // At the base level, the only task is to add reference counting data. Don't use
44*635a8641SAndroid Build Coastguard Worker // RefCountedThreadSafe since it requires the destructor to be a virtual method.
45*635a8641SAndroid Build Coastguard Worker // Creating a vtable for every BindState template instantiation results in a lot
46*635a8641SAndroid Build Coastguard Worker // of bloat. Its only task is to call the destructor which can be done with a
47*635a8641SAndroid Build Coastguard Worker // function pointer.
48*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT BindStateBase
49*635a8641SAndroid Build Coastguard Worker     : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
50*635a8641SAndroid Build Coastguard Worker  public:
51*635a8641SAndroid Build Coastguard Worker   REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
52*635a8641SAndroid Build Coastguard Worker 
53*635a8641SAndroid Build Coastguard Worker   using InvokeFuncStorage = void(*)();
54*635a8641SAndroid Build Coastguard Worker 
55*635a8641SAndroid Build Coastguard Worker  private:
56*635a8641SAndroid Build Coastguard Worker   BindStateBase(InvokeFuncStorage polymorphic_invoke,
57*635a8641SAndroid Build Coastguard Worker                 void (*destructor)(const BindStateBase*));
58*635a8641SAndroid Build Coastguard Worker   BindStateBase(InvokeFuncStorage polymorphic_invoke,
59*635a8641SAndroid Build Coastguard Worker                 void (*destructor)(const BindStateBase*),
60*635a8641SAndroid Build Coastguard Worker                 bool (*is_cancelled)(const BindStateBase*));
61*635a8641SAndroid Build Coastguard Worker 
62*635a8641SAndroid Build Coastguard Worker   ~BindStateBase() = default;
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker   friend struct BindStateBaseRefCountTraits;
65*635a8641SAndroid Build Coastguard Worker   friend class RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits>;
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker   friend class CallbackBase;
68*635a8641SAndroid Build Coastguard Worker   friend class CallbackBaseCopyable;
69*635a8641SAndroid Build Coastguard Worker 
70*635a8641SAndroid Build Coastguard Worker   // Whitelist subclasses that access the destructor of BindStateBase.
71*635a8641SAndroid Build Coastguard Worker   template <typename Functor, typename... BoundArgs>
72*635a8641SAndroid Build Coastguard Worker   friend struct BindState;
73*635a8641SAndroid Build Coastguard Worker   friend struct ::base::FakeBindState;
74*635a8641SAndroid Build Coastguard Worker 
IsCancelled()75*635a8641SAndroid Build Coastguard Worker   bool IsCancelled() const {
76*635a8641SAndroid Build Coastguard Worker     return is_cancelled_(this);
77*635a8641SAndroid Build Coastguard Worker   }
78*635a8641SAndroid Build Coastguard Worker 
79*635a8641SAndroid Build Coastguard Worker   // In C++, it is safe to cast function pointers to function pointers of
80*635a8641SAndroid Build Coastguard Worker   // another type. It is not okay to use void*. We create a InvokeFuncStorage
81*635a8641SAndroid Build Coastguard Worker   // that that can store our function pointer, and then cast it back to
82*635a8641SAndroid Build Coastguard Worker   // the original type on usage.
83*635a8641SAndroid Build Coastguard Worker   InvokeFuncStorage polymorphic_invoke_;
84*635a8641SAndroid Build Coastguard Worker 
85*635a8641SAndroid Build Coastguard Worker   // Pointer to a function that will properly destroy |this|.
86*635a8641SAndroid Build Coastguard Worker   void (*destructor_)(const BindStateBase*);
87*635a8641SAndroid Build Coastguard Worker   bool (*is_cancelled_)(const BindStateBase*);
88*635a8641SAndroid Build Coastguard Worker 
89*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BindStateBase);
90*635a8641SAndroid Build Coastguard Worker };
91*635a8641SAndroid Build Coastguard Worker 
92*635a8641SAndroid Build Coastguard Worker // Holds the Callback methods that don't require specialization to reduce
93*635a8641SAndroid Build Coastguard Worker // template bloat.
94*635a8641SAndroid Build Coastguard Worker // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
95*635a8641SAndroid Build Coastguard Worker // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
96*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT CallbackBase {
97*635a8641SAndroid Build Coastguard Worker  public:
98*635a8641SAndroid Build Coastguard Worker   inline CallbackBase(CallbackBase&& c) noexcept;
99*635a8641SAndroid Build Coastguard Worker   CallbackBase& operator=(CallbackBase&& c) noexcept;
100*635a8641SAndroid Build Coastguard Worker 
101*635a8641SAndroid Build Coastguard Worker   explicit CallbackBase(const CallbackBaseCopyable& c);
102*635a8641SAndroid Build Coastguard Worker   CallbackBase& operator=(const CallbackBaseCopyable& c);
103*635a8641SAndroid Build Coastguard Worker 
104*635a8641SAndroid Build Coastguard Worker   explicit CallbackBase(CallbackBaseCopyable&& c) noexcept;
105*635a8641SAndroid Build Coastguard Worker   CallbackBase& operator=(CallbackBaseCopyable&& c) noexcept;
106*635a8641SAndroid Build Coastguard Worker 
107*635a8641SAndroid Build Coastguard Worker   // Returns true if Callback is null (doesn't refer to anything).
is_null()108*635a8641SAndroid Build Coastguard Worker   bool is_null() const { return !bind_state_; }
109*635a8641SAndroid Build Coastguard Worker   explicit operator bool() const { return !is_null(); }
110*635a8641SAndroid Build Coastguard Worker 
111*635a8641SAndroid Build Coastguard Worker   // Returns true if the callback invocation will be nop due to an cancellation.
112*635a8641SAndroid Build Coastguard Worker   // It's invalid to call this on uninitialized callback.
113*635a8641SAndroid Build Coastguard Worker   bool IsCancelled() const;
114*635a8641SAndroid Build Coastguard Worker 
115*635a8641SAndroid Build Coastguard Worker   // Returns the Callback into an uninitialized state.
116*635a8641SAndroid Build Coastguard Worker   void Reset();
117*635a8641SAndroid Build Coastguard Worker 
118*635a8641SAndroid Build Coastguard Worker  protected:
119*635a8641SAndroid Build Coastguard Worker   using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker   // Returns true if this callback equals |other|. |other| may be null.
122*635a8641SAndroid Build Coastguard Worker   bool EqualsInternal(const CallbackBase& other) const;
123*635a8641SAndroid Build Coastguard Worker 
124*635a8641SAndroid Build Coastguard Worker   constexpr inline CallbackBase();
125*635a8641SAndroid Build Coastguard Worker 
126*635a8641SAndroid Build Coastguard Worker   // Allow initializing of |bind_state_| via the constructor to avoid default
127*635a8641SAndroid Build Coastguard Worker   // initialization of the scoped_refptr.
128*635a8641SAndroid Build Coastguard Worker   explicit inline CallbackBase(BindStateBase* bind_state);
129*635a8641SAndroid Build Coastguard Worker 
polymorphic_invoke()130*635a8641SAndroid Build Coastguard Worker   InvokeFuncStorage polymorphic_invoke() const {
131*635a8641SAndroid Build Coastguard Worker     return bind_state_->polymorphic_invoke_;
132*635a8641SAndroid Build Coastguard Worker   }
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker   // Force the destructor to be instantiated inside this translation unit so
135*635a8641SAndroid Build Coastguard Worker   // that our subclasses will not get inlined versions.  Avoids more template
136*635a8641SAndroid Build Coastguard Worker   // bloat.
137*635a8641SAndroid Build Coastguard Worker   ~CallbackBase();
138*635a8641SAndroid Build Coastguard Worker 
139*635a8641SAndroid Build Coastguard Worker   scoped_refptr<BindStateBase> bind_state_;
140*635a8641SAndroid Build Coastguard Worker };
141*635a8641SAndroid Build Coastguard Worker 
142*635a8641SAndroid Build Coastguard Worker constexpr CallbackBase::CallbackBase() = default;
143*635a8641SAndroid Build Coastguard Worker CallbackBase::CallbackBase(CallbackBase&&) noexcept = default;
CallbackBase(BindStateBase * bind_state)144*635a8641SAndroid Build Coastguard Worker CallbackBase::CallbackBase(BindStateBase* bind_state)
145*635a8641SAndroid Build Coastguard Worker     : bind_state_(AdoptRef(bind_state)) {}
146*635a8641SAndroid Build Coastguard Worker 
147*635a8641SAndroid Build Coastguard Worker // CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
148*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT CallbackBaseCopyable : public CallbackBase {
149*635a8641SAndroid Build Coastguard Worker  public:
150*635a8641SAndroid Build Coastguard Worker   CallbackBaseCopyable(const CallbackBaseCopyable& c);
151*635a8641SAndroid Build Coastguard Worker   CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept = default;
152*635a8641SAndroid Build Coastguard Worker   CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
153*635a8641SAndroid Build Coastguard Worker   CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
154*635a8641SAndroid Build Coastguard Worker 
155*635a8641SAndroid Build Coastguard Worker  protected:
156*635a8641SAndroid Build Coastguard Worker   constexpr CallbackBaseCopyable() = default;
CallbackBaseCopyable(BindStateBase * bind_state)157*635a8641SAndroid Build Coastguard Worker   explicit CallbackBaseCopyable(BindStateBase* bind_state)
158*635a8641SAndroid Build Coastguard Worker       : CallbackBase(bind_state) {}
159*635a8641SAndroid Build Coastguard Worker   ~CallbackBaseCopyable() = default;
160*635a8641SAndroid Build Coastguard Worker };
161*635a8641SAndroid Build Coastguard Worker 
162*635a8641SAndroid Build Coastguard Worker }  // namespace internal
163*635a8641SAndroid Build Coastguard Worker }  // namespace base
164*635a8641SAndroid Build Coastguard Worker 
165*635a8641SAndroid Build Coastguard Worker #endif  // BASE_CALLBACK_INTERNAL_H_
166