• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/atomic_ref_count.h"
12 #include "base/base_export.h"
13 #include "base/callback_forward.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 
17 namespace base {
18 namespace internal {
19 template <CopyMode copy_mode>
20 class CallbackBase;
21 
22 // BindStateBase is used to provide an opaque handle that the Callback
23 // class can use to represent a function object with bound arguments.  It
24 // behaves as an existential type that is used by a corresponding
25 // DoInvoke function to perform the function execution.  This allows
26 // us to shield the Callback class from the types of the bound argument via
27 // "type erasure."
28 // At the base level, the only task is to add reference counting data. Don't use
29 // RefCountedThreadSafe since it requires the destructor to be a virtual method.
30 // Creating a vtable for every BindState template instantiation results in a lot
31 // of bloat. Its only task is to call the destructor which can be done with a
32 // function pointer.
33 class BindStateBase {
34  protected:
BindStateBase(void (* destructor)(BindStateBase *))35   explicit BindStateBase(void (*destructor)(BindStateBase*))
36       : ref_count_(0), destructor_(destructor) {}
37   ~BindStateBase() = default;
38 
39  private:
40   friend class scoped_refptr<BindStateBase>;
41   template <CopyMode copy_mode>
42   friend class CallbackBase;
43 
44   void AddRef();
45   void Release();
46 
47   AtomicRefCount ref_count_;
48 
49   // Pointer to a function that will properly destroy |this|.
50   void (*destructor_)(BindStateBase*);
51 
52   DISALLOW_COPY_AND_ASSIGN(BindStateBase);
53 };
54 
55 // Holds the Callback methods that don't require specialization to reduce
56 // template bloat.
57 // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
58 // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
59 template <>
60 class BASE_EXPORT CallbackBase<CopyMode::MoveOnly> {
61  public:
62   CallbackBase(CallbackBase&& c);
63   CallbackBase& operator=(CallbackBase&& c);
64 
65   // Returns true if Callback is null (doesn't refer to anything).
is_null()66   bool is_null() const { return bind_state_.get() == NULL; }
67   explicit operator bool() const { return !is_null(); }
68 
69   // Returns the Callback into an uninitialized state.
70   void Reset();
71 
72  protected:
73   // In C++, it is safe to cast function pointers to function pointers of
74   // another type. It is not okay to use void*. We create a InvokeFuncStorage
75   // that that can store our function pointer, and then cast it back to
76   // the original type on usage.
77   using InvokeFuncStorage = void(*)();
78 
79   // Returns true if this callback equals |other|. |other| may be null.
80   bool EqualsInternal(const CallbackBase& other) const;
81 
82   // Allow initializing of |bind_state_| via the constructor to avoid default
83   // initialization of the scoped_refptr.  We do not also initialize
84   // |polymorphic_invoke_| here because doing a normal assignment in the
85   // derived Callback templates makes for much nicer compiler errors.
86   explicit CallbackBase(BindStateBase* bind_state);
87 
88   // Force the destructor to be instantiated inside this translation unit so
89   // that our subclasses will not get inlined versions.  Avoids more template
90   // bloat.
91   ~CallbackBase();
92 
93   scoped_refptr<BindStateBase> bind_state_;
94   InvokeFuncStorage polymorphic_invoke_ = nullptr;
95 };
96 
97 // CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
98 template <>
99 class BASE_EXPORT CallbackBase<CopyMode::Copyable>
100     : public CallbackBase<CopyMode::MoveOnly> {
101  public:
102   CallbackBase(const CallbackBase& c);
103   CallbackBase(CallbackBase&& c);
104   CallbackBase& operator=(const CallbackBase& c);
105   CallbackBase& operator=(CallbackBase&& c);
106  protected:
CallbackBase(BindStateBase * bind_state)107   explicit CallbackBase(BindStateBase* bind_state)
108       : CallbackBase<CopyMode::MoveOnly>(bind_state) {}
~CallbackBase()109   ~CallbackBase() {}
110 };
111 
112 extern template class CallbackBase<CopyMode::MoveOnly>;
113 extern template class CallbackBase<CopyMode::Copyable>;
114 
115 }  // namespace internal
116 }  // namespace base
117 
118 #endif  // BASE_CALLBACK_INTERNAL_H_
119