Index: third_party/WebKit/Source/core/dom/CrossThreadTask.h |
diff --git a/third_party/WebKit/Source/core/dom/CrossThreadTask.h b/third_party/WebKit/Source/core/dom/CrossThreadTask.h |
index a583340aa52492cb88b4dbd2251eb68772906cfc..051d73f2e9961123af3382bc34096749372e77bd 100644 |
--- a/third_party/WebKit/Source/core/dom/CrossThreadTask.h |
+++ b/third_party/WebKit/Source/core/dom/CrossThreadTask.h |
@@ -39,10 +39,10 @@ |
namespace blink { |
-// createCrossThreadTask(...) is ExecutionContextTask version of |
-// threadSafeBind(). |
-// Using WTF::bind() directly is not thread-safe due to temporary objects, see |
-// https://crbug.com/390851 for details. |
+// createCrossThreadTask(...) is similar to but safer than |
+// CallClosureTask::create(bind(...)) for cross-thread task posting. |
+// postTask(CallClosureTask::create(bind(...))) is not thread-safe |
+// due to temporary objects, see http://crbug.com/390851 for details. |
// |
// Example: |
// void func1(int, const String&); |
@@ -54,37 +54,44 @@ |
// bind(func1, 42, str); |
// bind(func1, 42, str.isolatedCopy()); |
// |
-// For functions: |
-// void functionEC(MP1, ..., MPn, ExecutionContext*); |
-// void function(MP1, ..., MPn); |
-// class C { |
-// void memberEC(MP1, ..., MPn, ExecutionContext*); |
-// void member(MP1, ..., MPn); |
-// }; |
-// We create tasks represented by std::unique_ptr<ExecutionContextTask>: |
-// createCrossThreadTask(functionEC, const P1& p1, ..., const Pn& pn); |
-// createCrossThreadTask(memberEC, C* ptr, const P1& p1, ..., const Pn& pn); |
-// createCrossThreadTask(function, const P1& p1, ..., const Pn& pn); |
-// createCrossThreadTask(member, C* ptr, const P1& p1, ..., const Pn& pn); |
-// (|ptr| can also be WeakPtr<C> or other pointer-like types) |
-// and then the following are called on the target thread: |
-// functionEC(p1, ..., pn, context); |
-// ptr->memberEC(p1, ..., pn, context); |
-// function(p1, ..., pn); |
-// ptr->member(p1, ..., pn); |
+// Usage: |
+// For functions: |
+// void functionEC(MP1, ..., MPn, ExecutionContext*); |
+// void function(MP1, ..., MPn); |
+// class C { |
+// void memberEC(MP1, ..., MPn, ExecutionContext*); |
+// void member(MP1, ..., MPn); |
+// }; |
+// We create tasks represented by PassOwnPtr<ExecutionContextTask>: |
+// [1] createCrossThreadTask(functionEC, const P1& p1, ..., const Pn& pn); |
+// [2] createCrossThreadTask(memberEC, C* ptr, const P1& p1, ..., const Pn& pn); |
+// [3] createCrossThreadTask(function, const P1& p1, ..., const Pn& pn); |
+// [4] createCrossThreadTask(member, C* ptr, const P1& p1, ..., const Pn& pn); |
+// [5] createCrossThreadTask(member, const WeakPtr<C>& ptr, const P1& p1, ..., const Pn& pn); |
+// [6] createCrossThreadTask(member, C* p0, const P1& p1, ..., const Pn& pn); |
+// and then the following are called on the target thread: |
+// [1] functionEC(p1, ..., pn, context); |
+// [2] ptr->memberEC(p1, ..., pn, context); |
+// [3] function(p1, ..., pn); |
+// [4,5] ptr->member(p1, ..., pn); |
+// [6] p0->member(p1, ..., pn); |
// |
// ExecutionContext: |
// |context| is supplied by the target thread. |
// |
// Deep copies by threadSafeBind(): |
-// |ptr|, |p1|, ..., |pn| are processed by threadSafeBind() and thus |
+// |p0|, |p1|, ..., |pn| are processed by threadSafeBind() and thus |
// CrossThreadCopier. |
// You don't have to call manually e.g. isolatedCopy(). |
// To pass things that cannot be copied by CrossThreadCopier |
// (e.g. pointers), use AllowCrossThreadAccess() explicitly. |
+// |ptr| is assumed safe to be passed across threads, and |
+// AllowCrossThreadAccess() is applied automatically. |
// RETTYPE, PS, and MPS are added as template parameters to circumvent MSVC 18.00.21005.1 (VS 2013) issues. |
+// [1] createCrossThreadTask() for non-member functions (with ExecutionContext* argument). |
+// (P = <P1, ..., Pn>, MP = <MP1, ..., MPn, ExecutionContext*>) |
template<typename... P, typename... MP, |
typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
typename std::enable_if<PS + 1 == MPS, RETTYPE>::type createCrossThreadTask(void (*function)(MP...), P&&... parameters) |
@@ -92,6 +99,17 @@ |
return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinity>::create(threadSafeBind<ExecutionContext*>(function, std::forward<P>(parameters)...)); |
} |
+// [2] createCrossThreadTask() for member functions of class C (with ExecutionContext* argument) + raw pointer (C*). |
+// (P = <P1, ..., Pn>, MP = <MP1, ..., MPn, ExecutionContext*>) |
+template<typename C, typename... P, typename... MP, |
+ typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
+typename std::enable_if<PS + 1 == MPS, RETTYPE>::type createCrossThreadTask(void (C::*function)(MP...), C* p, P&&... parameters) |
+{ |
+ return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinity>::create(threadSafeBind<ExecutionContext*>(function, AllowCrossThreadAccess(p), std::forward<P>(parameters)...)); |
+} |
+ |
+// [3] createCrossThreadTask() for non-member functions |
+// (P = <P1, ..., Pn>, MP = <MP1, ..., MPn>) |
template<typename... P, typename... MP, |
typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (*function)(MP...), P&&... parameters) |
@@ -99,18 +117,31 @@ |
return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSafeBind(function, std::forward<P>(parameters)...)); |
} |
+// [4] createCrossThreadTask() for member functions of class C + raw pointer (C*) |
+// [5] createCrossThreadTask() for member functions of class C + weak pointer (const WeakPtr<C>&) |
+// (P = <P1, ..., Pn>, MP = <MP1, ..., MPn>) |
template<typename C, typename... P, typename... MP, |
typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
-typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C::*function)(MP...), P&&... parameters) |
+typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C::*function)(MP...), C* p, P&&... parameters) |
{ |
- return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinity>::create(threadSafeBind<ExecutionContext*>(function, std::forward<P>(parameters)...)); |
+ return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSafeBind(function, AllowCrossThreadAccess(p), std::forward<P>(parameters)...)); |
} |
template<typename C, typename... P, typename... MP, |
typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
-typename std::enable_if<PS == MPS + 1, RETTYPE>::type createCrossThreadTask(void (C::*function)(MP...), P&&... parameters) |
+typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C::*function)(MP...), const WeakPtr<C>& p, P&&... parameters) |
{ |
- return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSafeBind(function, std::forward<P>(parameters)...)); |
+ return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSafeBind(function, AllowCrossThreadAccess(p), std::forward<P>(parameters)...)); |
+} |
+ |
+// [6] createCrossThreadTask() for member functions + pointers to class C other than C* or const WeakPtr<C>& |
+// (P = <P0, P1, ..., Pn>, MP = <MP1, ..., MPn>) |
+template<typename C, typename P0, typename... P, typename... MP, |
+ typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof...(P), size_t MPS = sizeof...(MP)> |
+typename std::enable_if<PS == MPS && !WTF::IsSubclassOfTemplate<typename std::decay<P0>::type, WeakPtr>::value && !std::is_pointer<typename std::decay<P0>::type>::value, RETTYPE>::type |
+createCrossThreadTask(void (C::*function)(MP...), P0&& parameter0, P&&... parameters) |
+{ |
+ return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSafeBind(function, std::forward<P0>(parameter0), std::forward<P>(parameters)...)); |
} |
} // namespace blink |