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 |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #ifndef WTF_Functional_h | 26 #ifndef WTF_Functional_h |
| 27 #define WTF_Functional_h | 27 #define WTF_Functional_h |
| 28 | 28 |
| 29 #include "base/bind.h" | 29 #include "base/bind.h" |
| 30 #include "base/threading/thread_checker.h" | |
| 30 #include "base/tuple.h" | 31 #include "base/tuple.h" |
| 31 #include "wtf/Allocator.h" | 32 #include "wtf/Allocator.h" |
| 32 #include "wtf/Assertions.h" | 33 #include "wtf/Assertions.h" |
| 33 #include "wtf/PassRefPtr.h" | 34 #include "wtf/PassRefPtr.h" |
| 34 #include "wtf/PtrUtil.h" | 35 #include "wtf/PtrUtil.h" |
| 35 #include "wtf/RefPtr.h" | 36 #include "wtf/RefPtr.h" |
| 36 #include "wtf/ThreadSafeRefCounted.h" | 37 #include "wtf/ThreadSafeRefCounted.h" |
| 37 #include "wtf/TypeTraits.h" | 38 #include "wtf/TypeTraits.h" |
| 38 #include "wtf/WeakPtr.h" | 39 #include "wtf/WeakPtr.h" |
| 39 #include <tuple> | 40 #include <tuple> |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 return UnretainedWrapper<T, SameThreadAffinity>(value); | 149 return UnretainedWrapper<T, SameThreadAffinity>(value); |
| 149 } | 150 } |
| 150 | 151 |
| 151 template <typename T> | 152 template <typename T> |
| 152 UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) | 153 UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) |
| 153 { | 154 { |
| 154 static_assert(!WTF::IsGarbageCollectedType<T>::value, "crossThreadUnretained () + GCed type is forbidden"); | 155 static_assert(!WTF::IsGarbageCollectedType<T>::value, "crossThreadUnretained () + GCed type is forbidden"); |
| 155 return UnretainedWrapper<T, CrossThreadAffinity>(value); | 156 return UnretainedWrapper<T, CrossThreadAffinity>(value); |
| 156 } | 157 } |
| 157 | 158 |
| 158 // A FunctionWrapper is a class template that can wrap a function pointer or a m ember function pointer and | |
| 159 // provide a unified interface for calling that function. | |
| 160 template <typename> | |
| 161 class FunctionWrapper; | |
| 162 | |
| 163 // Bound static functions: | |
| 164 template <typename R, typename... Parameters> | |
| 165 class FunctionWrapper<R(*)(Parameters...)> { | |
| 166 DISALLOW_NEW(); | |
| 167 public: | |
| 168 typedef R ResultType; | |
| 169 static const size_t numberOfArguments = sizeof...(Parameters); | |
| 170 | |
| 171 explicit FunctionWrapper(R(*function)(Parameters...)) | |
| 172 : m_function(function) | |
| 173 { | |
| 174 } | |
| 175 | |
| 176 template <typename... IncomingParameters> | |
| 177 R operator()(IncomingParameters&&... parameters) | |
| 178 { | |
| 179 return m_function(std::forward<IncomingParameters>(parameters)...); | |
| 180 } | |
| 181 | |
| 182 private: | |
| 183 R(*m_function)(Parameters...); | |
| 184 }; | |
| 185 | |
| 186 // Bound member functions: | |
| 187 | |
| 188 template <typename R, typename C, typename... Parameters> | |
| 189 class FunctionWrapper<R(C::*)(Parameters...)> { | |
| 190 DISALLOW_NEW(); | |
| 191 public: | |
| 192 typedef R ResultType; | |
| 193 // + 1 is for |this| as an argument. | |
| 194 static const size_t numberOfArguments = sizeof...(Parameters) + 1; | |
| 195 | |
| 196 explicit FunctionWrapper(R(C::*function)(Parameters...)) | |
| 197 : m_function(function) | |
| 198 { | |
| 199 } | |
| 200 | |
| 201 template <typename Receiver, typename... IncomingParameters> | |
| 202 R operator()(Receiver&& receiver, IncomingParameters&&... parameters) | |
| 203 { | |
| 204 if (base::IsWeakReceiver<typename std::decay<Receiver>::type>::value && !receiver) { | |
| 205 return R(); | |
| 206 } | |
| 207 | |
| 208 C& c = *receiver; | |
| 209 return (c.*m_function)(std::forward<IncomingParameters>(parameters)...); | |
| 210 } | |
| 211 | |
| 212 private: | |
| 213 R(C::*m_function)(Parameters...); | |
| 214 }; | |
| 215 | |
| 216 template <typename T> | 159 template <typename T> |
| 217 struct ParamStorageTraits { | 160 struct ParamStorageTraits { |
| 218 typedef T StorageType; | 161 typedef T StorageType; |
| 219 | 162 |
| 220 static_assert(!std::is_pointer<T>::value, "Raw pointers are not allowed to b ind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersistent, wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, RefPtr or unretained." ); | 163 static_assert(!std::is_pointer<T>::value, "Raw pointers are not allowed to b ind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersistent, wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, RefPtr or unretained." ); |
| 221 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && !IsSubclassO fTemplate<T, blink::WeakMember>::value, "Member and WeakMember are not allowed t o bind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersisten t, wrapCrossThreadPersistent or wrapCrossThreadWeakPersistent."); | 164 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && !IsSubclassO fTemplate<T, blink::WeakMember>::value, "Member and WeakMember are not allowed t o bind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersisten t, wrapCrossThreadPersistent or wrapCrossThreadWeakPersistent."); |
| 222 }; | 165 }; |
| 223 | 166 |
| 224 template <typename T> | 167 template <typename T> |
| 225 struct ParamStorageTraits<PassRefPtr<T>> { | 168 struct ParamStorageTraits<PassRefPtr<T>> { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { | 202 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { |
| 260 typedef UnretainedWrapper<T, threadAffinity> StorageType; | 203 typedef UnretainedWrapper<T, threadAffinity> StorageType; |
| 261 }; | 204 }; |
| 262 | 205 |
| 263 template <typename T, FunctionThreadAffinity threadAffinity> | 206 template <typename T, FunctionThreadAffinity threadAffinity> |
| 264 T* Unwrap(const UnretainedWrapper<T, threadAffinity>& wrapped) | 207 T* Unwrap(const UnretainedWrapper<T, threadAffinity>& wrapped) |
| 265 { | 208 { |
| 266 return wrapped.value(); | 209 return wrapped.value(); |
| 267 } | 210 } |
| 268 | 211 |
| 269 | 212 template<typename Signature, FunctionThreadAffinity threadAffinity = SameThreadA ffinity> |
| 270 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> | |
| 271 class Function; | 213 class Function; |
| 272 | 214 |
| 273 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> | 215 template<typename R, typename... Args, FunctionThreadAffinity threadAffinity> |
| 274 class Function<R(Args...), threadAffinity> { | 216 class Function<R(Args...), threadAffinity> { |
| 275 USING_FAST_MALLOC(Function); | 217 USING_FAST_MALLOC(Function); |
| 276 WTF_MAKE_NONCOPYABLE(Function); | 218 WTF_MAKE_NONCOPYABLE(Function); |
| 277 public: | 219 public: |
| 278 virtual ~Function() { } | 220 Function(base::Callback<R(Args...)> callback) |
| 279 virtual R operator()(Args... args) = 0; | 221 : m_callback(std::move(callback)) { } |
| 280 protected: | |
| 281 Function() = default; | |
| 282 void checkThread() { } | |
| 283 }; | |
| 284 | 222 |
| 285 #if ENABLE(ASSERT) | 223 ~Function() |
| 286 template<typename R, typename... Args> | |
| 287 class Function<R(Args...), SameThreadAffinity> { | |
| 288 USING_FAST_MALLOC(Function); | |
| 289 WTF_MAKE_NONCOPYABLE(Function); | |
| 290 public: | |
| 291 virtual ~Function() | |
| 292 { | 224 { |
| 293 checkThread(); | 225 DCHECK(m_threadChecker.CalledOnValidThread()); |
| 294 } | |
| 295 virtual R operator()(Args... args) = 0; | |
| 296 protected: | |
| 297 Function() | |
| 298 : m_createdThread(currentThread()) | |
| 299 { | |
| 300 } | 226 } |
| 301 | 227 |
| 302 void NEVER_INLINE checkThread() | 228 R operator()(Args... args) |
| 303 { | 229 { |
| 304 // Function with SameThreadAffinity, including SameThreadClosure | 230 DCHECK(m_threadChecker.CalledOnValidThread()); |
| 305 // created by WTF::bind() or blink::createSameThreadTask(), | 231 return m_callback.Run(std::forward<Args>(args)...); |
| 306 // must be called and destructed on the thread where it is created. | |
| 307 // If it is intended to be used cross-thread, use | |
| 308 // blink::threadSafeBind() or blink::createCrossThreadTask() instead. | |
| 309 RELEASE_ASSERT(m_createdThread == currentThread()); | |
| 310 } | 232 } |
| 311 | 233 |
| 312 private: | 234 private: |
| 313 const ThreadIdentifier m_createdThread; | 235 using MaybeThreadChecker = typename std::conditional< |
| 314 }; | 236 threadAffinity == SameThreadAffinity, |
| 315 #endif | 237 base::ThreadChecker, |
| 316 | 238 base::ThreadCheckerDoNothing>::type; |
| 317 template <FunctionThreadAffinity threadAffinity, typename BoundParametersTuple, typename FunctionWrapper, typename UnboundRunType> | 239 MaybeThreadChecker m_threadChecker; |
| 318 class PartBoundFunctionImpl; | 240 base::Callback<R(Args...)> m_callback; |
| 319 | |
| 320 template <FunctionThreadAffinity threadAffinity, typename... BoundParameters, ty pename FunctionWrapper, typename ResultType, typename... UnboundParameters> | |
| 321 class PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters...>, Func tionWrapper, ResultType(UnboundParameters...)> final : public Function<ResultTyp e(UnboundParameters...), threadAffinity> { | |
| 322 public: | |
| 323 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain | |
| 324 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. | |
| 325 // So, sadly, we have write down the full type signature in all places where storage traits are needed. | |
| 326 // | |
| 327 // template <typename T> | |
| 328 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; | |
| 329 | |
| 330 // Note that BoundParameters can be const T&, T&& or a mix of these. | |
| 331 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) | |
| 332 : m_functionWrapper(functionWrapper) | |
| 333 , m_bound(std::forward<BoundParameters>(bound)...) | |
| 334 { | |
| 335 } | |
| 336 | |
| 337 ResultType operator()(UnboundParameters... unbound) override | |
| 338 { | |
| 339 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to | |
| 340 // pass a list of indices to a worker function template. | |
| 341 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>( ), std::forward<UnboundParameters>(unbound)...); | |
| 342 } | |
| 343 | |
| 344 private: | |
| 345 template <std::size_t... boundIndices, typename... IncomingUnboundParameters > | |
| 346 ResultType callInternal(const base::IndexSequence<boundIndices...>&, Incomin gUnboundParameters&&... unbound) | |
| 347 { | |
| 348 this->checkThread(); | |
| 349 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. | |
| 350 using base::internal::Unwrap; | |
| 351 return m_functionWrapper(Unwrap(std::get<boundIndices>(m_bound))..., std ::forward<IncomingUnboundParameters>(unbound)...); | |
| 352 } | |
| 353 | |
| 354 FunctionWrapper m_functionWrapper; | |
| 355 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; | |
| 356 }; | 241 }; |
| 357 | 242 |
| 358 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> | 243 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> |
| 359 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) | 244 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) |
| 360 { | 245 { |
| 361 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound | 246 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound |
| 362 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th is type isn't actually created; | 247 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th is type isn't actually created; |
| 363 // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter | 248 // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter |
| 364 // pack can be used instead of std::tuple. std::tuple is used just because i t's most convenient for this purpose. | 249 // pack can be used instead of std::tuple. std::tuple is used just because i t's most convenient for this purpose. |
| 365 using UnboundRunType = base::MakeUnboundRunType<FunctionType, BoundParameter s...>; | 250 using UnboundRunType = base::MakeUnboundRunType<FunctionType, BoundParameter s...>; |
| 366 using BoundFunctionType = PartBoundFunctionImpl<threadAffinity, std::tuple<B oundParameters&&...>, FunctionWrapper<FunctionType>, UnboundRunType>; | 251 return wrapUnique(new Function<UnboundRunType, threadAffinity>(base::Bind(fu nction, typename ParamStorageTraits<typename std::decay<BoundParameters>::type>: :StorageType(std::forward<BoundParameters>(boundParameters))...))); |
|
Yuta Kitamura
2016/06/27 06:46:36
This line makes my brain cause a traffic jam... Le
tzik
2016/06/27 06:53:43
Agree. It's too long to look at a glance...
1. Yes
| |
| 367 return wrapUnique(new BoundFunctionType(FunctionWrapper<FunctionType>(functi on), std::forward<BoundParameters>(boundParameters)...)); | |
| 368 } | 252 } |
| 369 | 253 |
| 370 | |
| 371 | |
| 372 template <typename FunctionType, typename... BoundParameters> | 254 template <typename FunctionType, typename... BoundParameters> |
| 373 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, SameThreadAffinity>> bind(FunctionType function, BoundParameters&&... bound Parameters) | 255 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, SameThreadAffinity>> bind(FunctionType function, BoundParameters&&... bound Parameters) |
| 374 { | 256 { |
| 375 return bindInternal<SameThreadAffinity>(function, std::forward<BoundParamete rs>(boundParameters)...); | 257 return bindInternal<SameThreadAffinity>(function, std::forward<BoundParamete rs>(boundParameters)...); |
| 376 } | 258 } |
| 377 | 259 |
| 378 typedef Function<void(), SameThreadAffinity> SameThreadClosure; | 260 typedef Function<void(), SameThreadAffinity> SameThreadClosure; |
| 379 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; | 261 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; |
| 380 | 262 |
| 381 } // namespace WTF | 263 } // namespace WTF |
| 382 | 264 |
| 383 using WTF::bind; | 265 using WTF::bind; |
| 384 | 266 |
| 385 using WTF::passed; | 267 using WTF::passed; |
| 386 using WTF::unretained; | 268 using WTF::unretained; |
| 387 using WTF::crossThreadUnretained; | 269 using WTF::crossThreadUnretained; |
| 388 | 270 |
| 389 using WTF::Function; | 271 using WTF::Function; |
| 390 using WTF::SameThreadClosure; | 272 using WTF::SameThreadClosure; |
| 391 using WTF::CrossThreadClosure; | 273 using WTF::CrossThreadClosure; |
| 392 | 274 |
| 393 #endif // WTF_Functional_h | 275 #endif // WTF_Functional_h |
| OLD | NEW |