Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 108 enum FunctionThreadAffinity { | 108 enum FunctionThreadAffinity { |
| 109 CrossThreadAffinity, | 109 CrossThreadAffinity, |
| 110 SameThreadAffinity | 110 SameThreadAffinity |
| 111 }; | 111 }; |
| 112 | 112 |
| 113 template <typename T> | 113 template <typename T> |
| 114 class PassedWrapper final { | 114 class PassedWrapper final { |
| 115 public: | 115 public: |
| 116 explicit PassedWrapper(T&& scoper) : m_scoper(std::move(scoper)) { } | 116 explicit PassedWrapper(T&& scoper) : m_scoper(std::move(scoper)) { } |
| 117 PassedWrapper(PassedWrapper&& other) : m_scoper(std::move(other.m_scoper)) { } | 117 PassedWrapper(PassedWrapper&& other) : m_scoper(std::move(other.m_scoper)) { } |
| 118 T moveOut() { return std::move(m_scoper); } | 118 T moveOut() const { return std::move(m_scoper); } |
| 119 | 119 |
| 120 private: | 120 private: |
| 121 T m_scoper; | 121 mutable T m_scoper; |
| 122 }; | 122 }; |
| 123 | 123 |
| 124 template <typename T> | 124 template <typename T> |
| 125 PassedWrapper<T> passed(T&& value) | 125 PassedWrapper<T> passed(T&& value) |
| 126 { | 126 { |
| 127 static_assert(!std::is_reference<T>::value, | 127 static_assert(!std::is_reference<T>::value, |
| 128 "You must pass an rvalue to passed() so it can be moved. Add std::move() if necessary."); | 128 "You must pass an rvalue to passed() so it can be moved. Add std::move() if necessary."); |
| 129 static_assert(!std::is_const<T>::value, "|value| must not be const so it can be moved."); | 129 static_assert(!std::is_const<T>::value, "|value| must not be const so it can be moved."); |
| 130 return PassedWrapper<T>(std::move(value)); | 130 return PassedWrapper<T>(std::move(value)); |
| 131 } | 131 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 private: | 211 private: |
| 212 R(C::*m_function)(Parameters...); | 212 R(C::*m_function)(Parameters...); |
| 213 }; | 213 }; |
| 214 | 214 |
| 215 template <typename T> | 215 template <typename T> |
| 216 struct ParamStorageTraits { | 216 struct ParamStorageTraits { |
| 217 typedef T StorageType; | 217 typedef T StorageType; |
| 218 | 218 |
| 219 static_assert(!std::is_pointer<T>::value, "Raw pointer is not allowed to bin d into WTF::Function. Wrap it with either Persistent, WeakPersistent, CrossThrea dPersistent, CrossThreadWeakPersistent, RefPtr or unretained."); | 219 static_assert(!std::is_pointer<T>::value, "Raw pointer is not allowed to bin d into WTF::Function. Wrap it with either Persistent, WeakPersistent, CrossThrea dPersistent, CrossThreadWeakPersistent, RefPtr or unretained."); |
| 220 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value, "Member is not allowed to bind into WTF::Function. Wrap it with either Persistent, WeakPersist ent, CrossThreadPersistent or CrossThreadWeakPersistenst."); | 220 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value, "Member is not allowed to bind into WTF::Function. Wrap it with either Persistent, WeakPersist ent, CrossThreadPersistent or CrossThreadWeakPersistenst."); |
| 221 | |
| 222 static StorageType wrap(const T& value) { return value; } // Copy. | |
| 223 static StorageType wrap(T&& value) { return std::move(value); } | |
| 224 | |
| 225 // Don't move out, because the functor may be called multiple times. | |
| 226 static const T& unwrap(const StorageType& value) { return value; } | |
| 227 }; | 221 }; |
| 228 | 222 |
| 229 template <typename T> | 223 template <typename T> |
| 230 struct ParamStorageTraits<PassRefPtr<T>> { | 224 struct ParamStorageTraits<PassRefPtr<T>> { |
| 231 typedef RefPtr<T> StorageType; | 225 typedef RefPtr<T> StorageType; |
| 232 | |
| 233 static StorageType wrap(PassRefPtr<T> value) { return value; } | |
| 234 static T* unwrap(const StorageType& value) { return value.get(); } | |
| 235 }; | 226 }; |
| 236 | 227 |
| 237 template <typename T> | 228 template <typename T> |
| 238 struct ParamStorageTraits<RefPtr<T>> { | 229 struct ParamStorageTraits<RefPtr<T>> { |
| 239 typedef RefPtr<T> StorageType; | 230 typedef RefPtr<T> StorageType; |
| 231 }; | |
| 240 | 232 |
| 241 static StorageType wrap(RefPtr<T> value) { return value.release(); } | 233 template <typename T> |
| 242 static T* unwrap(const StorageType& value) { return value.get(); } | 234 T* Unwrap(const RefPtr<T>& wrapped) |
| 243 }; | 235 { |
| 236 return wrapped.get(); | |
| 237 } | |
| 244 | 238 |
| 245 template <typename> class RetainPtr; | 239 template <typename> class RetainPtr; |
| 246 | 240 |
| 247 template <typename T> | 241 template <typename T> |
| 248 struct ParamStorageTraits<RetainPtr<T>> { | 242 struct ParamStorageTraits<RetainPtr<T>> { |
| 249 typedef RetainPtr<T> StorageType; | 243 typedef RetainPtr<T> StorageType; |
| 250 | |
| 251 static StorageType wrap(const RetainPtr<T>& value) { return value; } | |
| 252 static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { ret urn value.get(); } | |
| 253 }; | 244 }; |
| 254 | 245 |
| 255 template <typename T> | 246 template <typename T> |
| 256 struct ParamStorageTraits<PassedWrapper<T>> { | 247 struct ParamStorageTraits<PassedWrapper<T>> { |
| 257 typedef PassedWrapper<T> StorageType; | 248 typedef PassedWrapper<T> StorageType; |
| 249 }; | |
| 258 | 250 |
| 259 static StorageType wrap(PassedWrapper<T>&& value) { return std::move(value); } | 251 template <typename T> |
| 260 static T unwrap(StorageType& value) { return value.moveOut(); } | 252 T Unwrap(const PassedWrapper<T>& wrapped) |
|
Yuta Kitamura
2016/06/24 12:21:09
Is the "const&" the part of API requirement of Unw
tzik
2016/06/24 13:04:20
Yes, it's going to be required.
This will be used
| |
| 261 }; | 253 { |
| 254 return wrapped.moveOut(); | |
| 255 } | |
| 262 | 256 |
| 263 template <typename T, FunctionThreadAffinity threadAffinity> | 257 template <typename T, FunctionThreadAffinity threadAffinity> |
| 264 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { | 258 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { |
| 265 typedef UnretainedWrapper<T, threadAffinity> StorageType; | 259 typedef UnretainedWrapper<T, threadAffinity> StorageType; |
| 260 }; | |
| 266 | 261 |
| 267 static StorageType wrap(const UnretainedWrapper<T, threadAffinity>& value) { return value; } | 262 template <typename T, FunctionThreadAffinity threadAffinity> |
| 268 static T* unwrap(const StorageType& value) { return value.value(); } | 263 T* Unwrap(const UnretainedWrapper<T, threadAffinity>& wrapped) |
| 269 }; | 264 { |
| 265 return wrapped.value(); | |
| 266 } | |
| 267 | |
| 270 | 268 |
| 271 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> | 269 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> |
| 272 class Function; | 270 class Function; |
| 273 | 271 |
| 274 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> | 272 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> |
| 275 class Function<R(Args...), threadAffinity> { | 273 class Function<R(Args...), threadAffinity> { |
| 276 USING_FAST_MALLOC(Function); | 274 USING_FAST_MALLOC(Function); |
| 277 WTF_MAKE_NONCOPYABLE(Function); | 275 WTF_MAKE_NONCOPYABLE(Function); |
| 278 public: | 276 public: |
| 279 virtual ~Function() { } | 277 virtual ~Function() { } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain | 322 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain |
| 325 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. | 323 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. |
| 326 // So, sadly, we have write down the full type signature in all places where storage traits are needed. | 324 // So, sadly, we have write down the full type signature in all places where storage traits are needed. |
| 327 // | 325 // |
| 328 // template <typename T> | 326 // template <typename T> |
| 329 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; | 327 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; |
| 330 | 328 |
| 331 // Note that BoundParameters can be const T&, T&& or a mix of these. | 329 // Note that BoundParameters can be const T&, T&& or a mix of these. |
| 332 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) | 330 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) |
| 333 : m_functionWrapper(functionWrapper) | 331 : m_functionWrapper(functionWrapper) |
| 334 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type> ::wrap(std::forward<BoundParameters>(bound))...) | 332 , m_bound(std::forward<BoundParameters>(bound)...) |
| 335 { | 333 { |
| 336 } | 334 } |
| 337 | 335 |
| 338 ResultType operator()(UnboundParameters... unbound) override | 336 ResultType operator()(UnboundParameters... unbound) override |
| 339 { | 337 { |
| 340 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to | 338 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to |
| 341 // pass a list of indices to a worker function template. | 339 // pass a list of indices to a worker function template. |
| 342 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>( ), std::forward<UnboundParameters>(unbound)...); | 340 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>( ), std::forward<UnboundParameters>(unbound)...); |
| 343 } | 341 } |
| 344 | 342 |
| 345 private: | 343 private: |
| 346 template <std::size_t... boundIndices, typename... IncomingUnboundParameters > | 344 template <std::size_t... boundIndices, typename... IncomingUnboundParameters > |
| 347 ResultType callInternal(const base::IndexSequence<boundIndices...>&, Incomin gUnboundParameters&&... unbound) | 345 ResultType callInternal(const base::IndexSequence<boundIndices...>&, Incomin gUnboundParameters&&... unbound) |
| 348 { | 346 { |
| 349 this->checkThread(); | 347 this->checkThread(); |
| 350 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. | 348 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. |
| 351 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., std::forward<Incomi ngUnboundParameters>(unbound)...); | 349 using base::internal::Unwrap; |
| 350 return m_functionWrapper(Unwrap(std::get<boundIndices>(m_bound))..., std ::forward<IncomingUnboundParameters>(unbound)...); | |
| 352 } | 351 } |
| 353 | 352 |
| 354 FunctionWrapper m_functionWrapper; | 353 FunctionWrapper m_functionWrapper; |
| 355 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; | 354 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; |
| 356 }; | 355 }; |
| 357 | 356 |
| 358 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> | 357 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> |
| 359 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) | 358 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) |
| 360 { | 359 { |
| 361 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound | 360 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 384 | 383 |
| 385 using WTF::passed; | 384 using WTF::passed; |
| 386 using WTF::unretained; | 385 using WTF::unretained; |
| 387 using WTF::crossThreadUnretained; | 386 using WTF::crossThreadUnretained; |
| 388 | 387 |
| 389 using WTF::Function; | 388 using WTF::Function; |
| 390 using WTF::SameThreadClosure; | 389 using WTF::SameThreadClosure; |
| 391 using WTF::CrossThreadClosure; | 390 using WTF::CrossThreadClosure; |
| 392 | 391 |
| 393 #endif // WTF_Functional_h | 392 #endif // WTF_Functional_h |
| OLD | NEW |