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> | |
| 12 #include <memory> | |
| 13 #include <type_traits> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/atomic_ref_count.h" | 11 #include "base/atomic_ref_count.h" |
| 17 #include "base/base_export.h" | 12 #include "base/base_export.h" |
| 18 #include "base/callback_forward.h" | 13 #include "base/callback_forward.h" |
| 19 #include "base/macros.h" | 14 #include "base/macros.h" |
| 20 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 21 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 22 | 17 |
| 23 namespace base { | 18 namespace base { |
| 24 namespace internal { | 19 namespace internal { |
| 25 template <CopyMode copy_mode> | 20 template <CopyMode copy_mode> |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 CallbackBase& operator=(CallbackBase&& c); | 105 CallbackBase& operator=(CallbackBase&& c); |
| 111 protected: | 106 protected: |
| 112 explicit CallbackBase(BindStateBase* bind_state) | 107 explicit CallbackBase(BindStateBase* bind_state) |
| 113 : CallbackBase<CopyMode::MoveOnly>(bind_state) {} | 108 : CallbackBase<CopyMode::MoveOnly>(bind_state) {} |
| 114 ~CallbackBase() {} | 109 ~CallbackBase() {} |
| 115 }; | 110 }; |
| 116 | 111 |
| 117 extern template class CallbackBase<CopyMode::MoveOnly>; | 112 extern template class CallbackBase<CopyMode::MoveOnly>; |
| 118 extern template class CallbackBase<CopyMode::Copyable>; | 113 extern template class CallbackBase<CopyMode::Copyable>; |
| 119 | 114 |
| 120 // A helper template to determine if given type is non-const move-only-type, | |
| 121 // i.e. if a value of the given type should be passed via std::move() in a | |
| 122 // destructive way. Types are considered to be move-only if they have a | |
| 123 // sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using | |
| 124 // the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. | |
| 125 // It would be easy to generalize this trait to all move-only types... but this | |
| 126 // confuses template deduction in VS2013 with certain types such as | |
| 127 // std::unique_ptr. | |
| 128 // TODO(dcheng): Revisit this when Windows switches to VS2015 by default. | |
| 129 | |
| 130 template <typename T> struct IsMoveOnlyType { | |
| 131 // Types YesType and NoType are guaranteed such that sizeof(YesType) < | |
| 132 // sizeof(NoType). | |
| 133 using YesType = char; | |
| 134 struct NoType { YesType dummy[2]; }; | |
| 135 | |
| 136 template <typename U> | |
| 137 static YesType Test(const typename U::MoveOnlyTypeForCPP03*); | |
| 138 | |
| 139 template <typename U> | |
| 140 static NoType Test(...); | |
| 141 | |
| 142 static const bool value = sizeof((Test<T>(0))) == sizeof(YesType) && | |
| 143 !std::is_const<T>::value; | |
| 144 }; | |
| 145 | |
| 146 // Specialization of IsMoveOnlyType so that std::unique_ptr is still considered | |
| 147 // move-only, even without the sentinel member. | |
| 148 template <typename T, typename D> | |
| 149 struct IsMoveOnlyType<std::unique_ptr<T, D>> : std::true_type {}; | |
| 150 | |
| 151 // Specialization of std::vector, so that it's considered move-only if the | |
| 152 // element type is move-only. Allocator is explicitly ignored when determining | |
| 153 // move-only status of the std::vector. | |
| 154 template <typename T, typename Allocator> | |
| 155 struct IsMoveOnlyType<std::vector<T, Allocator>> : IsMoveOnlyType<T> {}; | |
| 156 | |
| 157 template <typename> | |
| 158 struct CallbackParamTraitsForMoveOnlyType; | |
| 159 | |
| 160 template <typename> | |
| 161 struct CallbackParamTraitsForNonMoveOnlyType; | |
| 162 | |
| 163 // TODO(tzik): Use a default parameter once MSVS supports variadic templates | |
| 164 // with default values. | |
| 165 // http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilat ion-error-with-variadic-templates | |
| 166 // | |
| 167 // This is a typetraits object that's used to take an argument type, and | |
| 168 // extract a suitable type for forwarding arguments. | |
| 169 template <typename T> | |
| 170 struct CallbackParamTraits | |
| 171 : std::conditional<IsMoveOnlyType<T>::value, | |
| 172 CallbackParamTraitsForMoveOnlyType<T>, | |
| 173 CallbackParamTraitsForNonMoveOnlyType<T>>::type { | |
| 174 }; | |
| 175 | |
| 176 template <typename T> | |
| 177 struct CallbackParamTraitsForNonMoveOnlyType { | |
| 178 using ForwardType = const T&; | |
| 179 }; | |
| 180 | |
| 181 // Note that for array types, we implicitly add a const in the conversion. This | |
| 182 // means that it is not possible to bind array arguments to functions that take | |
| 183 // a non-const pointer. Trying to specialize the template based on a "const | |
| 184 // T[n]" does not seem to match correctly, so we are stuck with this | |
| 185 // restriction. | |
| 186 template <typename T, size_t n> | |
| 187 struct CallbackParamTraitsForNonMoveOnlyType<T[n]> { | |
| 188 using ForwardType = const T*; | |
| 189 }; | |
| 190 | |
| 191 // See comment for CallbackParamTraits<T[n]>. | |
| 192 template <typename T> | |
| 193 struct CallbackParamTraitsForNonMoveOnlyType<T[]> { | |
| 194 using ForwardType = const T*; | |
| 195 }; | |
| 196 | |
| 197 // Parameter traits for movable-but-not-copyable scopers. | |
| 198 // | |
| 199 // Callback<>/Bind() understands movable-but-not-copyable semantics where | |
| 200 // the type cannot be copied but can still have its state destructively | |
| 201 // transferred (aka. moved) to another instance of the same type by calling a | |
| 202 // helper function. When used with Bind(), this signifies transferal of the | |
| 203 // object's state to the target function. | |
| 204 // | |
| 205 // For these types, the ForwardType must not be a const reference, or a | |
| 206 // reference. A const reference is inappropriate, and would break const | |
| 207 // correctness, because we are implementing a destructive move. A non-const | |
| 208 // reference cannot be used with temporaries which means the result of a | |
| 209 // function or a cast would not be usable with Callback<> or Bind(). | |
| 210 template <typename T> | |
| 211 struct CallbackParamTraitsForMoveOnlyType { | |
| 212 using ForwardType = T; | |
| 213 }; | |
| 214 | |
| 215 // CallbackForward() is a very limited simulation of C++11's std::forward() | |
| 216 // used by the Callback/Bind system for a set of movable-but-not-copyable | |
| 217 // types. It is needed because forwarding a movable-but-not-copyable | |
| 218 // argument to another function requires us to invoke the proper move | |
| 219 // operator to create a rvalue version of the type. The supported types are | |
| 220 // whitelisted below as overloads of the CallbackForward() function. The | |
| 221 // default template compiles out to be a no-op. | |
| 222 // | |
| 223 // In C++11, std::forward would replace all uses of this function. However, it | |
| 224 // is impossible to implement a general std::forward without C++11 due to a lack | |
| 225 // of rvalue references. | |
| 226 // | |
| 227 // In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to | |
| 228 // simulate std::forward() and forward the result of one Callback as a | |
| 229 // parameter to another callback. This is to support Callbacks that return | |
| 230 // the movable-but-not-copyable types whitelisted above. | |
| 231 template <typename T> | |
| 232 typename std::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward( | |
|
Nico
2016/03/10 21:54:50
Don't we lose this protection now? Or does std::fo
tzik
2016/03/14 08:49:42
Do you mean a protection to prevent moving non-mov
| |
| 233 T& t) { | |
| 234 return t; | |
| 235 } | |
| 236 | |
| 237 template <typename T> | |
| 238 typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( | |
| 239 T& t) { | |
| 240 return std::move(t); | |
| 241 } | |
| 242 | |
| 243 } // namespace internal | 115 } // namespace internal |
| 244 } // namespace base | 116 } // namespace base |
| 245 | 117 |
| 246 #endif // BASE_CALLBACK_INTERNAL_H_ | 118 #endif // BASE_CALLBACK_INTERNAL_H_ |
| OLD | NEW |