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