Chromium Code Reviews| 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 |