OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains utility functions and classes that help the | 5 // This file contains utility functions and classes that help the |
6 // implementation, and management of the Callback objects. | 6 // implementation, and management of the Callback objects. |
7 | 7 |
8 #ifndef BASE_CALLBACK_INTERNAL_H_ | 8 #ifndef BASE_CALLBACK_INTERNAL_H_ |
9 #define BASE_CALLBACK_INTERNAL_H_ | 9 #define BASE_CALLBACK_INTERNAL_H_ |
10 | 10 |
11 #include <stddef.h> | 11 #include <stddef.h> |
12 #include <memory> | 12 #include <memory> |
13 #include <type_traits> | 13 #include <type_traits> |
14 #include <vector> | 14 #include <vector> |
15 | 15 |
16 #include "base/atomic_ref_count.h" | 16 #include "base/atomic_ref_count.h" |
17 #include "base/base_export.h" | 17 #include "base/base_export.h" |
18 #include "base/callback_forward.h" | |
18 #include "base/macros.h" | 19 #include "base/macros.h" |
19 #include "base/memory/ref_counted.h" | 20 #include "base/memory/ref_counted.h" |
20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
21 #include "base/template_util.h" | 22 #include "base/template_util.h" |
22 | 23 |
23 namespace base { | 24 namespace base { |
24 namespace internal { | 25 namespace internal { |
26 template <CopyMode copy_mode> | |
25 class CallbackBase; | 27 class CallbackBase; |
26 | 28 |
27 // BindStateBase is used to provide an opaque handle that the Callback | 29 // BindStateBase is used to provide an opaque handle that the Callback |
28 // class can use to represent a function object with bound arguments. It | 30 // class can use to represent a function object with bound arguments. It |
29 // behaves as an existential type that is used by a corresponding | 31 // behaves as an existential type that is used by a corresponding |
30 // DoInvoke function to perform the function execution. This allows | 32 // DoInvoke function to perform the function execution. This allows |
31 // us to shield the Callback class from the types of the bound argument via | 33 // us to shield the Callback class from the types of the bound argument via |
32 // "type erasure." | 34 // "type erasure." |
33 // At the base level, the only task is to add reference counting data. Don't use | 35 // At the base level, the only task is to add reference counting data. Don't use |
34 // RefCountedThreadSafe since it requires the destructor to be a virtual method. | 36 // RefCountedThreadSafe since it requires the destructor to be a virtual method. |
35 // Creating a vtable for every BindState template instantiation results in a lot | 37 // Creating a vtable for every BindState template instantiation results in a lot |
36 // of bloat. Its only task is to call the destructor which can be done with a | 38 // of bloat. Its only task is to call the destructor which can be done with a |
37 // function pointer. | 39 // function pointer. |
38 class BindStateBase { | 40 class BindStateBase { |
39 protected: | 41 protected: |
40 explicit BindStateBase(void (*destructor)(BindStateBase*)) | 42 explicit BindStateBase(void (*destructor)(BindStateBase*)) |
41 : ref_count_(0), destructor_(destructor) {} | 43 : ref_count_(0), destructor_(destructor) {} |
42 ~BindStateBase() = default; | 44 ~BindStateBase() = default; |
43 | 45 |
44 private: | 46 private: |
45 friend class scoped_refptr<BindStateBase>; | 47 friend class scoped_refptr<BindStateBase>; |
48 template <CopyMode copy_mode> | |
46 friend class CallbackBase; | 49 friend class CallbackBase; |
47 | 50 |
48 void AddRef(); | 51 void AddRef(); |
49 void Release(); | 52 void Release(); |
50 | 53 |
51 AtomicRefCount ref_count_; | 54 AtomicRefCount ref_count_; |
52 | 55 |
53 // Pointer to a function that will properly destroy |this|. | 56 // Pointer to a function that will properly destroy |this|. |
54 void (*destructor_)(BindStateBase*); | 57 void (*destructor_)(BindStateBase*); |
55 | 58 |
56 DISALLOW_COPY_AND_ASSIGN(BindStateBase); | 59 DISALLOW_COPY_AND_ASSIGN(BindStateBase); |
57 }; | 60 }; |
58 | 61 |
59 // Holds the Callback methods that don't require specialization to reduce | 62 // Holds the Callback methods that don't require specialization to reduce |
60 // template bloat. | 63 // template bloat. |
61 class BASE_EXPORT CallbackBase { | 64 // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and |
65 // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation. | |
66 template <> | |
67 class BASE_EXPORT CallbackBase<CopyMode::MoveOnly> { | |
62 public: | 68 public: |
63 CallbackBase(const CallbackBase& c); | 69 CallbackBase(CallbackBase&& c); |
64 CallbackBase& operator=(const CallbackBase& c); | 70 CallbackBase& operator=(CallbackBase&& c); |
65 | 71 |
66 // Returns true if Callback is null (doesn't refer to anything). | 72 // Returns true if Callback is null (doesn't refer to anything). |
67 bool is_null() const { return bind_state_.get() == NULL; } | 73 bool is_null() const { return bind_state_.get() == NULL; } |
68 | 74 |
69 // Returns the Callback into an uninitialized state. | 75 // Returns the Callback into an uninitialized state. |
70 void Reset(); | 76 void Reset(); |
71 | 77 |
72 protected: | 78 protected: |
73 // In C++, it is safe to cast function pointers to function pointers of | 79 // 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 | 80 // 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 | 81 // that that can store our function pointer, and then cast it back to |
76 // the original type on usage. | 82 // the original type on usage. |
77 using InvokeFuncStorage = void(*)(); | 83 using InvokeFuncStorage = void(*)(); |
78 | 84 |
79 // Returns true if this callback equals |other|. |other| may be null. | 85 // Returns true if this callback equals |other|. |other| may be null. |
80 bool Equals(const CallbackBase& other) const; | 86 bool EqualsInternal(const CallbackBase& other) const; |
81 | 87 |
82 // Allow initializing of |bind_state_| via the constructor to avoid default | 88 // Allow initializing of |bind_state_| via the constructor to avoid default |
83 // initialization of the scoped_refptr. We do not also initialize | 89 // initialization of the scoped_refptr. We do not also initialize |
84 // |polymorphic_invoke_| here because doing a normal assignment in the | 90 // |polymorphic_invoke_| here because doing a normal assignment in the |
85 // derived Callback templates makes for much nicer compiler errors. | 91 // derived Callback templates makes for much nicer compiler errors. |
86 explicit CallbackBase(BindStateBase* bind_state); | 92 CallbackBase(BindStateBase* bind_state); |
dcheng
2016/03/02 08:02:36
Just curious: why can this no longer be explicit?
tzik
2016/03/02 08:13:14
Oh, I just overlook this. I forgot to add it when
tzik
2016/03/02 13:09:52
Done.
| |
87 | 93 |
88 // Force the destructor to be instantiated inside this translation unit so | 94 // Force the destructor to be instantiated inside this translation unit so |
89 // that our subclasses will not get inlined versions. Avoids more template | 95 // that our subclasses will not get inlined versions. Avoids more template |
90 // bloat. | 96 // bloat. |
91 ~CallbackBase(); | 97 ~CallbackBase(); |
92 | 98 |
93 scoped_refptr<BindStateBase> bind_state_; | 99 scoped_refptr<BindStateBase> bind_state_; |
94 InvokeFuncStorage polymorphic_invoke_; | 100 InvokeFuncStorage polymorphic_invoke_ = nullptr; |
95 }; | 101 }; |
96 | 102 |
103 // CallbackBase<Copyable> is a direct base class of Copyable Callbacks. | |
104 template <> | |
105 class BASE_EXPORT CallbackBase<CopyMode::Copyable> | |
106 : public CallbackBase<CopyMode::MoveOnly> { | |
107 public: | |
108 CallbackBase(const CallbackBase& c); | |
109 CallbackBase(CallbackBase&& c); | |
110 CallbackBase& operator=(const CallbackBase& c); | |
111 CallbackBase& operator=(CallbackBase&& c); | |
112 protected: | |
113 CallbackBase(BindStateBase* bind_state) | |
114 : CallbackBase<CopyMode::MoveOnly>(bind_state) {} | |
115 ~CallbackBase() {} | |
116 }; | |
117 | |
118 extern template class CallbackBase<CopyMode::MoveOnly>; | |
119 extern template class CallbackBase<CopyMode::Copyable>; | |
120 | |
97 // A helper template to determine if given type is non-const move-only-type, | 121 // A helper template to determine if given type is non-const move-only-type, |
98 // i.e. if a value of the given type should be passed via std::move() in a | 122 // i.e. if a value of the given type should be passed via std::move() in a |
99 // destructive way. Types are considered to be move-only if they have a | 123 // destructive way. Types are considered to be move-only if they have a |
100 // sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using | 124 // sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using |
101 // the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. | 125 // the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. |
102 // It would be easy to generalize this trait to all move-only types... but this | 126 // It would be easy to generalize this trait to all move-only types... but this |
103 // confuses template deduction in VS2013 with certain types such as | 127 // confuses template deduction in VS2013 with certain types such as |
104 // std::unique_ptr. | 128 // std::unique_ptr. |
105 // TODO(dcheng): Revisit this when Windows switches to VS2015 by default. | 129 // TODO(dcheng): Revisit this when Windows switches to VS2015 by default. |
106 template <typename T> struct IsMoveOnlyType { | 130 template <typename T> struct IsMoveOnlyType { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 template <typename T> | 232 template <typename T> |
209 typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( | 233 typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( |
210 T& t) { | 234 T& t) { |
211 return std::move(t); | 235 return std::move(t); |
212 } | 236 } |
213 | 237 |
214 } // namespace internal | 238 } // namespace internal |
215 } // namespace base | 239 } // namespace base |
216 | 240 |
217 #endif // BASE_CALLBACK_INTERNAL_H_ | 241 #endif // BASE_CALLBACK_INTERNAL_H_ |
OLD | NEW |