Index: third_party/WebKit/Source/core/dom/ExecutionContextTask.h |
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContextTask.h b/third_party/WebKit/Source/core/dom/ExecutionContextTask.h |
index 328d068caa5ff16f1c70adcd1dcf5a9d8fb678e4..15818c90bfd9e39301cd6d41e94fd744d30a1580 100644 |
--- a/third_party/WebKit/Source/core/dom/ExecutionContextTask.h |
+++ b/third_party/WebKit/Source/core/dom/ExecutionContextTask.h |
@@ -28,11 +28,13 @@ |
#define ExecutionContextTask_h |
#include "core/CoreExport.h" |
+#include "platform/CrossThreadFunctional.h" |
#include "wtf/Allocator.h" |
#include "wtf/Functional.h" |
#include "wtf/Noncopyable.h" |
#include "wtf/PtrUtil.h" |
#include "wtf/text/WTFString.h" |
+#include <type_traits> |
namespace blink { |
@@ -106,6 +108,56 @@ std::unique_ptr<ExecutionContextTask> createSameThreadTask( |
return internal::createCallClosureTask(WTF::bind(function, std::forward<P>(parameters)...)); |
} |
+// createCrossThreadTask(...) is ExecutionContextTask version of |
+// crossThreadBind(). |
+// Using WTF::bind() directly is not thread-safe due to temporary objects, see |
+// https://crbug.com/390851 for details. |
+// |
+// Example: |
+// void func1(int, const String&); |
+// createCrossThreadTask(func1, 42, str); |
+// func1(42, str2) will be called, where |str2| is a deep copy of |
+// |str| (created by str.isolatedCopy()). |
+// |
+// Don't (if you pass the task across threads): |
+// 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); |
+// |
+// ExecutionContext: |
+// |context| is supplied by the target thread. |
+// |
+// Deep copies by crossThreadBind(): |
+// |ptr|, |p1|, ..., |pn| are processed by crossThreadBind() 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 crossThreadUnretained() explicitly. |
+ |
+template<typename FunctionType, typename... P> |
+std::unique_ptr<ExecutionContextTask> createCrossThreadTask(FunctionType function, P&&... parameters) |
+{ |
+ return internal::createCallClosureTask(crossThreadBind(function, std::forward<P>(parameters)...)); |
+} |
+ |
} // namespace blink |
#endif |