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/macros.h" | 18 #include "base/macros.h" |
19 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
20 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
21 #include "base/template_util.h" | 21 #include "base/template_util.h" |
22 | 22 |
23 namespace base { | 23 namespace base { |
24 namespace internal { | 24 namespace internal { |
25 class CallbackBase; | 25 class MoveOnlyCallbackBase; |
26 | 26 |
27 // BindStateBase is used to provide an opaque handle that the Callback | 27 // BindStateBase is used to provide an opaque handle that the Callback |
28 // class can use to represent a function object with bound arguments. It | 28 // class can use to represent a function object with bound arguments. It |
29 // behaves as an existential type that is used by a corresponding | 29 // behaves as an existential type that is used by a corresponding |
30 // DoInvoke function to perform the function execution. This allows | 30 // DoInvoke function to perform the function execution. This allows |
31 // us to shield the Callback class from the types of the bound argument via | 31 // us to shield the Callback class from the types of the bound argument via |
32 // "type erasure." | 32 // "type erasure." |
33 // At the base level, the only task is to add reference counting data. Don't use | 33 // 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. | 34 // RefCountedThreadSafe since it requires the destructor to be a virtual method. |
35 // Creating a vtable for every BindState template instantiation results in a lot | 35 // 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 | 36 // of bloat. Its only task is to call the destructor which can be done with a |
37 // function pointer. | 37 // function pointer. |
38 class BindStateBase { | 38 class BindStateBase { |
39 protected: | 39 protected: |
40 explicit BindStateBase(void (*destructor)(BindStateBase*)) | 40 explicit BindStateBase(void (*destructor)(BindStateBase*)) |
41 : ref_count_(0), destructor_(destructor) {} | 41 : ref_count_(0), destructor_(destructor) {} |
42 ~BindStateBase() = default; | 42 ~BindStateBase() = default; |
43 | 43 |
44 private: | 44 private: |
45 friend class scoped_refptr<BindStateBase>; | 45 friend class scoped_refptr<BindStateBase>; |
46 friend class CallbackBase; | 46 friend class MoveOnlyCallbackBase; |
47 | 47 |
48 void AddRef(); | 48 void AddRef(); |
49 void Release(); | 49 void Release(); |
50 | 50 |
51 AtomicRefCount ref_count_; | 51 AtomicRefCount ref_count_; |
52 | 52 |
53 // Pointer to a function that will properly destroy |this|. | 53 // Pointer to a function that will properly destroy |this|. |
54 void (*destructor_)(BindStateBase*); | 54 void (*destructor_)(BindStateBase*); |
55 | 55 |
56 DISALLOW_COPY_AND_ASSIGN(BindStateBase); | 56 DISALLOW_COPY_AND_ASSIGN(BindStateBase); |
57 }; | 57 }; |
58 | 58 |
59 // Holds the Callback methods that don't require specialization to reduce | 59 // Holds the Callback methods that don't require specialization to reduce |
60 // template bloat. | 60 // template bloat. |
61 class BASE_EXPORT CallbackBase { | 61 // MoveOnlyCallbackBase is a direct base class of MoveOnly callbacks, and |
62 // CopyableCallbackBase uses MoveOnlyCallbackBase for its implementation. | |
63 class BASE_EXPORT MoveOnlyCallbackBase { | |
62 public: | 64 public: |
63 CallbackBase(const CallbackBase& c); | 65 MoveOnlyCallbackBase(MoveOnlyCallbackBase&& c); |
64 CallbackBase& operator=(const CallbackBase& c); | 66 MoveOnlyCallbackBase& operator=(MoveOnlyCallbackBase&& c); |
65 | 67 |
66 // Returns true if Callback is null (doesn't refer to anything). | 68 // Returns true if Callback is null (doesn't refer to anything). |
67 bool is_null() const { return bind_state_.get() == NULL; } | 69 bool is_null() const { return bind_state_.get() == NULL; } |
68 | 70 |
69 // Returns the Callback into an uninitialized state. | 71 // Returns the Callback into an uninitialized state. |
70 void Reset(); | 72 void Reset(); |
71 | 73 |
72 protected: | 74 protected: |
73 // In C++, it is safe to cast function pointers to function pointers of | 75 // 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 | 76 // 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 | 77 // that that can store our function pointer, and then cast it back to |
76 // the original type on usage. | 78 // the original type on usage. |
77 using InvokeFuncStorage = void(*)(); | 79 using InvokeFuncStorage = void(*)(); |
78 | 80 |
79 // Returns true if this callback equals |other|. |other| may be null. | 81 // Returns true if this callback equals |other|. |other| may be null. |
80 bool Equals(const CallbackBase& other) const; | 82 bool EqualsInternal(const MoveOnlyCallbackBase& other) const; |
81 | 83 |
82 // Allow initializing of |bind_state_| via the constructor to avoid default | 84 void set_bind_state(BindStateBase* bind_state); |
83 // initialization of the scoped_refptr. We do not also initialize | 85 |
84 // |polymorphic_invoke_| here because doing a normal assignment in the | 86 MoveOnlyCallbackBase(); |
85 // derived Callback templates makes for much nicer compiler errors. | |
86 explicit CallbackBase(BindStateBase* bind_state); | |
dcheng
2016/02/16 23:12:26
Why change this from initializing in the ctor to u
tzik
2016/02/17 00:46:56
That is a workaround of a MSVC 2013 bug. It doesn'
dcheng
2016/02/29 17:51:58
Just curious, but does this have any effect on bin
tzik
2016/03/01 07:31:33
Done. Now, the stripped binary size on Linux is th
| |
87 | 87 |
88 // Force the destructor to be instantiated inside this translation unit so | 88 // Force the destructor to be instantiated inside this translation unit so |
89 // that our subclasses will not get inlined versions. Avoids more template | 89 // that our subclasses will not get inlined versions. Avoids more template |
90 // bloat. | 90 // bloat. |
91 ~CallbackBase(); | 91 ~MoveOnlyCallbackBase(); |
92 | 92 |
93 scoped_refptr<BindStateBase> bind_state_; | 93 scoped_refptr<BindStateBase> bind_state_; |
94 InvokeFuncStorage polymorphic_invoke_; | 94 InvokeFuncStorage polymorphic_invoke_ = nullptr; |
95 }; | |
96 | |
97 // CopyableCallbackBase is a direct base class of Copyable Callbacks. | |
98 class BASE_EXPORT CopyableCallbackBase : public MoveOnlyCallbackBase { | |
99 public: | |
100 CopyableCallbackBase(const CopyableCallbackBase& c); | |
101 CopyableCallbackBase(CopyableCallbackBase&& c); | |
102 CopyableCallbackBase& operator=(const CopyableCallbackBase& c); | |
103 CopyableCallbackBase& operator=(CopyableCallbackBase&& c); | |
104 protected: | |
105 CopyableCallbackBase() {} | |
106 ~CopyableCallbackBase() {} | |
95 }; | 107 }; |
96 | 108 |
97 // A helper template to determine if given type is non-const move-only-type, | 109 // 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 | 110 // 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 | 111 // destructive way. Types are considered to be move-only if they have a |
100 // sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using | 112 // sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using |
101 // the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. | 113 // 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 | 114 // 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 | 115 // confuses template deduction in VS2013 with certain types such as |
104 // std::unique_ptr. | 116 // std::unique_ptr. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 template <typename T> | 220 template <typename T> |
209 typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( | 221 typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( |
210 T& t) { | 222 T& t) { |
211 return std::move(t); | 223 return std::move(t); |
212 } | 224 } |
213 | 225 |
214 } // namespace internal | 226 } // namespace internal |
215 } // namespace base | 227 } // namespace base |
216 | 228 |
217 #endif // BASE_CALLBACK_INTERNAL_H_ | 229 #endif // BASE_CALLBACK_INTERNAL_H_ |
OLD | NEW |