blob: a9215fc9be8c1d2c0a8e46a367e84314b66781e0 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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
5// This file contains utility functions and classes that help the
6// implementation, and management of the Callback objects.
7
8#ifndef BASE_CALLBACK_INTERNAL_H_
9#define BASE_CALLBACK_INTERNAL_H_
10
David Ghandehari9e5b5872016-07-28 09:50:04 -070011#include "base/base_export.h"
Andrew Top0d1858f2019-05-15 22:01:47 -070012#include "base/callback_forward.h"
13#include "base/macros.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070014#include "base/memory/ref_counted.h"
David Ghandehari9e5b5872016-07-28 09:50:04 -070015
16namespace base {
Andrew Top0d1858f2019-05-15 22:01:47 -070017
18struct FakeBindState;
19
David Ghandehari9e5b5872016-07-28 09:50:04 -070020namespace internal {
21
Andrew Top0d1858f2019-05-15 22:01:47 -070022class CallbackBase;
23class CallbackBaseCopyable;
24
25class BindStateBase;
26
27template <typename Functor, typename... BoundArgs>
28struct BindState;
29
30struct BindStateBaseRefCountTraits {
31 static void Destruct(const BindStateBase*);
32};
33
34template <typename T>
35#if defined(STARBOARD) && defined(SB_IS_COMPILER_MSVC)
36// On MSVC, std::conditional_t does not return true with some equal types.
37using PassingType = T&&;
38#else
39using PassingType = std::conditional_t<std::is_scalar<T>::value, T, T&&>;
40#endif
41
David Ghandehari9e5b5872016-07-28 09:50:04 -070042// BindStateBase is used to provide an opaque handle that the Callback
43// class can use to represent a function object with bound arguments. It
44// behaves as an existential type that is used by a corresponding
45// DoInvoke function to perform the function execution. This allows
46// us to shield the Callback class from the types of the bound argument via
47// "type erasure."
Andrew Top0d1858f2019-05-15 22:01:47 -070048// At the base level, the only task is to add reference counting data. Don't use
49// RefCountedThreadSafe since it requires the destructor to be a virtual method.
50// Creating a vtable for every BindState template instantiation results in a lot
51// of bloat. Its only task is to call the destructor which can be done with a
52// function pointer.
53class BASE_EXPORT BindStateBase
54 : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
55 public:
56 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
57
58 enum CancellationQueryMode {
59 IS_CANCELLED,
60 MAYBE_VALID,
61 };
62
63 using InvokeFuncStorage = void(*)();
64
65 private:
66 BindStateBase(InvokeFuncStorage polymorphic_invoke,
67 void (*destructor)(const BindStateBase*));
68 BindStateBase(InvokeFuncStorage polymorphic_invoke,
69 void (*destructor)(const BindStateBase*),
70 bool (*query_cancellation_traits)(const BindStateBase*,
71 CancellationQueryMode mode));
72
73 ~BindStateBase() = default;
74
75 friend struct BindStateBaseRefCountTraits;
76 friend class RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits>;
77
78 friend class CallbackBase;
79 friend class CallbackBaseCopyable;
80
81 // Whitelist subclasses that access the destructor of BindStateBase.
82 template <typename Functor, typename... BoundArgs>
83 friend struct BindState;
84 friend struct ::base::FakeBindState;
85
86 bool IsCancelled() const {
87 return query_cancellation_traits_(this, IS_CANCELLED);
88 }
89
90 bool MaybeValid() const {
91 return query_cancellation_traits_(this, MAYBE_VALID);
92 }
93
94 // In C++, it is safe to cast function pointers to function pointers of
95 // another type. It is not okay to use void*. We create a InvokeFuncStorage
96 // that that can store our function pointer, and then cast it back to
97 // the original type on usage.
98 InvokeFuncStorage polymorphic_invoke_;
99
100 // Pointer to a function that will properly destroy |this|.
101 void (*destructor_)(const BindStateBase*);
102 bool (*query_cancellation_traits_)(const BindStateBase*,
103 CancellationQueryMode mode);
104
105 DISALLOW_COPY_AND_ASSIGN(BindStateBase);
David Ghandehari9e5b5872016-07-28 09:50:04 -0700106};
107
108// Holds the Callback methods that don't require specialization to reduce
109// template bloat.
Andrew Top0d1858f2019-05-15 22:01:47 -0700110// CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
111// CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
David Ghandehari9e5b5872016-07-28 09:50:04 -0700112class BASE_EXPORT CallbackBase {
113 public:
Andrew Top0d1858f2019-05-15 22:01:47 -0700114 inline CallbackBase(CallbackBase&& c) noexcept;
115 CallbackBase& operator=(CallbackBase&& c) noexcept;
116
117 explicit CallbackBase(const CallbackBaseCopyable& c);
118 CallbackBase& operator=(const CallbackBaseCopyable& c);
119
120 explicit CallbackBase(CallbackBaseCopyable&& c) noexcept;
121 CallbackBase& operator=(CallbackBaseCopyable&& c) noexcept;
122
David Ghandehari9e5b5872016-07-28 09:50:04 -0700123 // Returns true if Callback is null (doesn't refer to anything).
Andrew Top0d1858f2019-05-15 22:01:47 -0700124 bool is_null() const { return !bind_state_; }
125 explicit operator bool() const { return !is_null(); }
126
127 // Returns true if the callback invocation will be nop due to an cancellation.
128 // It's invalid to call this on uninitialized callback.
129 //
130 // Must be called on the Callback's destination sequence.
131 bool IsCancelled() const;
132
133 // If this returns false, the callback invocation will be a nop due to a
134 // cancellation. This may(!) still return true, even on a cancelled callback.
135 //
136 // This function is thread-safe.
137 bool MaybeValid() const;
David Ghandehari9e5b5872016-07-28 09:50:04 -0700138
139 // Returns the Callback into an uninitialized state.
140 void Reset();
141
142 protected:
Andrew Top0d1858f2019-05-15 22:01:47 -0700143 using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
David Ghandehari9e5b5872016-07-28 09:50:04 -0700144
145 // Returns true if this callback equals |other|. |other| may be null.
Andrew Top0d1858f2019-05-15 22:01:47 -0700146 bool EqualsInternal(const CallbackBase& other) const;
147
148 constexpr inline CallbackBase();
David Ghandehari9e5b5872016-07-28 09:50:04 -0700149
150 // Allow initializing of |bind_state_| via the constructor to avoid default
Andrew Top0d1858f2019-05-15 22:01:47 -0700151 // initialization of the scoped_refptr.
152 explicit inline CallbackBase(BindStateBase* bind_state);
153
154 InvokeFuncStorage polymorphic_invoke() const {
155 return bind_state_->polymorphic_invoke_;
156 }
David Ghandehari9e5b5872016-07-28 09:50:04 -0700157
158 // Force the destructor to be instantiated inside this translation unit so
159 // that our subclasses will not get inlined versions. Avoids more template
160 // bloat.
161 ~CallbackBase();
162
163 scoped_refptr<BindStateBase> bind_state_;
David Ghandehari9e5b5872016-07-28 09:50:04 -0700164};
165
Andrew Top0d1858f2019-05-15 22:01:47 -0700166constexpr CallbackBase::CallbackBase() = default;
167CallbackBase::CallbackBase(CallbackBase&&) noexcept = default;
168CallbackBase::CallbackBase(BindStateBase* bind_state)
169 : bind_state_(AdoptRef(bind_state)) {}
170
171// CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
172class BASE_EXPORT CallbackBaseCopyable : public CallbackBase {
173 public:
174 CallbackBaseCopyable(const CallbackBaseCopyable& c);
175 CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept = default;
176 CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
177 CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
178
179 protected:
180 constexpr CallbackBaseCopyable() = default;
181 explicit CallbackBaseCopyable(BindStateBase* bind_state)
182 : CallbackBase(bind_state) {}
183 ~CallbackBaseCopyable() = default;
David Ghandehari9e5b5872016-07-28 09:50:04 -0700184};
185
David Ghandehari9e5b5872016-07-28 09:50:04 -0700186} // namespace internal
187} // namespace base
188
189#endif // BASE_CALLBACK_INTERNAL_H_