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 |