Chromium Code Reviews| Index: third_party/WebKit/Source/wtf/Functional.h |
| diff --git a/third_party/WebKit/Source/wtf/Functional.h b/third_party/WebKit/Source/wtf/Functional.h |
| index d254fd900030641338e13a91a556b3ce19dca36a..8d25909680343619cbcd2e7e9455c24c2f93c35c 100644 |
| --- a/third_party/WebKit/Source/wtf/Functional.h |
| +++ b/third_party/WebKit/Source/wtf/Functional.h |
| @@ -176,11 +176,16 @@ template<> struct ParamStorageTraits<void*> { |
| static void* unwrap(const StorageType& value) { return value; } |
| }; |
| -template<typename> |
| +enum FunctionThreadAffinity { |
| + CrossThreadAffinity, |
| + SameThreadAffinity |
| +}; |
| + |
| +template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> |
| class Function; |
| -template<typename R, typename... Args> |
| -class Function<R(Args...)> { |
| +template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> |
| +class Function<R(Args...), threadAffinity> { |
| USING_FAST_MALLOC(Function); |
| WTF_MAKE_NONCOPYABLE(Function); |
| public: |
| @@ -188,13 +193,41 @@ public: |
| virtual R operator()(Args... args) = 0; |
| protected: |
| Function() = default; |
| + void checkThread() { } |
| }; |
| -template <typename BoundParametersTuple, typename FunctionWrapper, typename... UnboundParameters> |
| +#if ENABLE(ASSERT) |
| +template<typename R, typename... Args> |
| +class Function<R(Args...), SameThreadAffinity> { |
| + USING_FAST_MALLOC(Function); |
| + WTF_MAKE_NONCOPYABLE(Function); |
| +public: |
| + virtual ~Function() |
| + { |
| + checkThread(); |
| + } |
| + virtual R operator()(Args... args) = 0; |
| +protected: |
| + Function() |
| + : m_createdThread(currentThread()) |
| + { |
| + } |
| + |
| + void NEVER_INLINE checkThread() |
|
kinuko
2016/03/02 07:30:56
sorry, why we need this to be noinline?
hiroshige
2016/03/03 02:21:07
This is to make checkThread() to appear in the cra
|
| + { |
| + RELEASE_ASSERT(m_createdThread == currentThread()); |
| + } |
| + |
| +private: |
| + ThreadIdentifier m_createdThread; |
| +}; |
| +#endif |
| + |
| +template <FunctionThreadAffinity threadAffinity, typename BoundParametersTuple, typename FunctionWrapper, typename... UnboundParameters> |
| class PartBoundFunctionImpl; |
| -template <typename... BoundParameters, typename FunctionWrapper, typename... UnboundParameters> |
| -class PartBoundFunctionImpl<std::tuple<BoundParameters...>, FunctionWrapper, UnboundParameters...> final : public Function<typename FunctionWrapper::ResultType(UnboundParameters...)> { |
| +template <FunctionThreadAffinity threadAffinity, typename... BoundParameters, typename FunctionWrapper, typename... UnboundParameters> |
| +class PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters...>, FunctionWrapper, UnboundParameters...> final : public Function<typename FunctionWrapper::ResultType(UnboundParameters...), threadAffinity> { |
| public: |
| // We would like to use StorageTraits<UnboundParameters>... with StorageTraits defined as below in order to obtain |
| // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. |
| @@ -221,6 +254,7 @@ private: |
| template <std::size_t... boundIndices> |
| typename FunctionWrapper::ResultType callInternal(UnboundParameters... unbound, const base::IndexSequence<boundIndices...>&) |
| { |
| + this->checkThread(); |
| // Get each element in m_bound, unwrap them, and call the function with the desired arguments. |
| return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundParameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., unbound...); |
| } |
| @@ -229,23 +263,31 @@ private: |
| std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>::type>::StorageType...> m_bound; |
| }; |
| -template <typename... UnboundParameters, typename FunctionType, typename... BoundParameters> |
| -PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundParameters...)>> bind(FunctionType function, BoundParameters&&... boundParameters) |
| +template <FunctionThreadAffinity threadAffinity, typename... UnboundParameters, typename FunctionType, typename... BoundParameters> |
| +PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundParameters...), threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... boundParameters) |
| { |
| // Bound parameters' types are wrapped with std::tuple so we can pass two template parameter packs (bound |
| // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of this type isn't actually created; |
| // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter |
| // pack can be used instead of std::tuple. std::tuple is used just because it's most convenient for this purpose. |
| - using BoundFunctionType = PartBoundFunctionImpl<std::tuple<BoundParameters&&...>, FunctionWrapper<FunctionType>, UnboundParameters...>; |
| + using BoundFunctionType = PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters&&...>, FunctionWrapper<FunctionType>, UnboundParameters...>; |
| return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function), std::forward<BoundParameters>(boundParameters)...)); |
| } |
| -typedef Function<void()> Closure; |
| +template <typename... UnboundParameters, typename FunctionType, typename... BoundParameters> |
| +PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundParameters...), SameThreadAffinity>> bind(FunctionType function, BoundParameters&&... boundParameters) |
| +{ |
| + return bindInternal<SameThreadAffinity, UnboundParameters...>(function, std::forward<BoundParameters>(boundParameters)...); |
| +} |
| + |
| +typedef Function<void(), SameThreadAffinity> Closure; |
| +typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; |
| } // namespace WTF |
| using WTF::Function; |
| using WTF::bind; |
| using WTF::Closure; |
| +using WTF::CrossThreadClosure; |
| #endif // WTF_Functional_h |