Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Unified Diff: third_party/WebKit/Source/wtf/Functional.h

Issue 1549143002: Add thread affinity and ASSERT() for same-thread restriction to WTF::Function (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@TRV_ThreadSafeBindByVariadicTemplate
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698