| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009-2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2009-2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #define CrossThreadTask_h | 32 #define CrossThreadTask_h |
| 33 | 33 |
| 34 #include "core/dom/ExecutionContext.h" | 34 #include "core/dom/ExecutionContext.h" |
| 35 #include "core/dom/ExecutionContextTask.h" | 35 #include "core/dom/ExecutionContextTask.h" |
| 36 #include "platform/ThreadSafeFunctional.h" | 36 #include "platform/ThreadSafeFunctional.h" |
| 37 #include "wtf/PassOwnPtr.h" | 37 #include "wtf/PassOwnPtr.h" |
| 38 #include <type_traits> | 38 #include <type_traits> |
| 39 | 39 |
| 40 namespace blink { | 40 namespace blink { |
| 41 | 41 |
| 42 // createCrossThreadTask(...) is similar to but safer than | 42 // createCrossThreadTask(...) is ExecutionContextTask version of |
| 43 // CallClosureTask::create(bind(...)) for cross-thread task posting. | 43 // threadSafeBind(). |
| 44 // postTask(CallClosureTask::create(bind(...))) is not thread-safe | 44 // Using WTF::bind() directly is not thread-safe due to temporary objects, see |
| 45 // due to temporary objects, see http://crbug.com/390851 for details. | 45 // https://crbug.com/390851 for details. |
| 46 // | 46 // |
| 47 // Example: | 47 // Example: |
| 48 // void func1(int, const String&); | 48 // void func1(int, const String&); |
| 49 // createCrossThreadTask(func1, 42, str); | 49 // createCrossThreadTask(func1, 42, str); |
| 50 // func1(42, str2) will be called, where |str2| is a deep copy of | 50 // func1(42, str2) will be called, where |str2| is a deep copy of |
| 51 // |str| (created by str.isolatedCopy()). | 51 // |str| (created by str.isolatedCopy()). |
| 52 // | 52 // |
| 53 // Don't (if you pass the task across threads): | 53 // Don't (if you pass the task across threads): |
| 54 // bind(func1, 42, str); | 54 // bind(func1, 42, str); |
| 55 // bind(func1, 42, str.isolatedCopy()); | 55 // bind(func1, 42, str.isolatedCopy()); |
| 56 // | 56 // |
| 57 // Usage: | 57 // For functions: |
| 58 // For functions: | 58 // void functionEC(MP1, ..., MPn, ExecutionContext*); |
| 59 // void functionEC(MP1, ..., MPn, ExecutionContext*); | 59 // void function(MP1, ..., MPn); |
| 60 // void function(MP1, ..., MPn); | 60 // class C { |
| 61 // class C { | 61 // void memberEC(MP1, ..., MPn, ExecutionContext*); |
| 62 // void memberEC(MP1, ..., MPn, ExecutionContext*); | 62 // void member(MP1, ..., MPn); |
| 63 // void member(MP1, ..., MPn); | 63 // }; |
| 64 // }; | 64 // We create tasks represented by std::unique_ptr<ExecutionContextTask>: |
| 65 // We create tasks represented by PassOwnPtr<ExecutionContextTask>: | 65 // createCrossThreadTask(functionEC, const P1& p1, ..., const Pn& pn); |
| 66 // [1] createCrossThreadTask(functionEC, const P1& p1, ..., const Pn& pn
); | 66 // createCrossThreadTask(memberEC, C* ptr, const P1& p1, ..., const Pn& pn); |
| 67 // [2] createCrossThreadTask(memberEC, C* ptr, const P1& p1, ..., const
Pn& pn); | 67 // createCrossThreadTask(function, const P1& p1, ..., const Pn& pn); |
| 68 // [3] createCrossThreadTask(function, const P1& p1, ..., const Pn& pn); | 68 // createCrossThreadTask(member, C* ptr, const P1& p1, ..., const Pn& pn); |
| 69 // [4] createCrossThreadTask(member, C* ptr, const P1& p1, ..., const Pn
& pn); | 69 // (|ptr| can also be WeakPtr<C> or other pointer-like types) |
| 70 // [5] createCrossThreadTask(member, const WeakPtr<C>& ptr, const P1& p1
, ..., const Pn& pn); | 70 // and then the following are called on the target thread: |
| 71 // [6] createCrossThreadTask(member, C* p0, const P1& p1, ..., const Pn&
pn); | 71 // functionEC(p1, ..., pn, context); |
| 72 // and then the following are called on the target thread: | 72 // ptr->memberEC(p1, ..., pn, context); |
| 73 // [1] functionEC(p1, ..., pn, context); | 73 // function(p1, ..., pn); |
| 74 // [2] ptr->memberEC(p1, ..., pn, context); | 74 // ptr->member(p1, ..., pn); |
| 75 // [3] function(p1, ..., pn); | |
| 76 // [4,5] ptr->member(p1, ..., pn); | |
| 77 // [6] p0->member(p1, ..., pn); | |
| 78 // | 75 // |
| 79 // ExecutionContext: | 76 // ExecutionContext: |
| 80 // |context| is supplied by the target thread. | 77 // |context| is supplied by the target thread. |
| 81 // | 78 // |
| 82 // Deep copies by threadSafeBind(): | 79 // Deep copies by threadSafeBind(): |
| 83 // |p0|, |p1|, ..., |pn| are processed by threadSafeBind() and thus | 80 // |ptr|, |p1|, ..., |pn| are processed by threadSafeBind() and thus |
| 84 // CrossThreadCopier. | 81 // CrossThreadCopier. |
| 85 // You don't have to call manually e.g. isolatedCopy(). | 82 // You don't have to call manually e.g. isolatedCopy(). |
| 86 // To pass things that cannot be copied by CrossThreadCopier | 83 // To pass things that cannot be copied by CrossThreadCopier |
| 87 // (e.g. pointers), use AllowCrossThreadAccess() explicitly. | 84 // (e.g. pointers), use AllowCrossThreadAccess() explicitly. |
| 88 // |ptr| is assumed safe to be passed across threads, and | |
| 89 // AllowCrossThreadAccess() is applied automatically. | |
| 90 | 85 |
| 91 // RETTYPE, PS, and MPS are added as template parameters to circumvent MSVC 18.0
0.21005.1 (VS 2013) issues. | 86 // RETTYPE, PS, and MPS are added as template parameters to circumvent MSVC 18.0
0.21005.1 (VS 2013) issues. |
| 92 | 87 |
| 93 // [1] createCrossThreadTask() for non-member functions (with ExecutionContext*
argument). | |
| 94 // (P = <P1, ..., Pn>, MP = <MP1, ..., MPn, ExecutionContext*>) | |
| 95 template<typename... P, typename... MP, | 88 template<typename... P, typename... MP, |
| 96 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | 89 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> |
| 97 typename std::enable_if<PS + 1 == MPS, RETTYPE>::type createCrossThreadTask(void
(*function)(MP...), P&&... parameters) | 90 typename std::enable_if<PS + 1 == MPS, RETTYPE>::type createCrossThreadTask(void
(*function)(MP...), P&&... parameters) |
| 98 { | 91 { |
| 99 return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinit
y>::create(threadSafeBind<ExecutionContext*>(function, std::forward<P>(parameter
s)...)); | 92 return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinit
y>::create(threadSafeBind<ExecutionContext*>(function, std::forward<P>(parameter
s)...)); |
| 100 } | 93 } |
| 101 | 94 |
| 102 // [2] createCrossThreadTask() for member functions of class C (with ExecutionCo
ntext* argument) + raw pointer (C*). | |
| 103 // (P = <P1, ..., Pn>, MP = <MP1, ..., MPn, ExecutionContext*>) | |
| 104 template<typename C, typename... P, typename... MP, | |
| 105 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | |
| 106 typename std::enable_if<PS + 1 == MPS, RETTYPE>::type createCrossThreadTask(void
(C::*function)(MP...), C* p, P&&... parameters) | |
| 107 { | |
| 108 return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinit
y>::create(threadSafeBind<ExecutionContext*>(function, AllowCrossThreadAccess(p)
, std::forward<P>(parameters)...)); | |
| 109 } | |
| 110 | |
| 111 // [3] createCrossThreadTask() for non-member functions | |
| 112 // (P = <P1, ..., Pn>, MP = <MP1, ..., MPn>) | |
| 113 template<typename... P, typename... MP, | 95 template<typename... P, typename... MP, |
| 114 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | 96 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> |
| 115 typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (*f
unction)(MP...), P&&... parameters) | 97 typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (*f
unction)(MP...), P&&... parameters) |
| 116 { | 98 { |
| 117 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, std::forward<P>(parameters)...)); | 99 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, std::forward<P>(parameters)...)); |
| 118 } | 100 } |
| 119 | 101 |
| 120 // [4] createCrossThreadTask() for member functions of class C + raw pointer (C*
) | |
| 121 // [5] createCrossThreadTask() for member functions of class C + weak pointer (c
onst WeakPtr<C>&) | |
| 122 // (P = <P1, ..., Pn>, MP = <MP1, ..., MPn>) | |
| 123 template<typename C, typename... P, typename... MP, | |
| 124 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | |
| 125 typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C:
:*function)(MP...), C* p, P&&... parameters) | |
| 126 { | |
| 127 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, AllowCrossThreadAccess(p), std::forward<P>(parameters)...)); | |
| 128 } | |
| 129 | |
| 130 template<typename C, typename... P, typename... MP, | 102 template<typename C, typename... P, typename... MP, |
| 131 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | 103 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> |
| 132 typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C:
:*function)(MP...), const WeakPtr<C>& p, P&&... parameters) | 104 typename std::enable_if<PS == MPS, RETTYPE>::type createCrossThreadTask(void (C:
:*function)(MP...), P&&... parameters) |
| 133 { | 105 { |
| 134 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, AllowCrossThreadAccess(p), std::forward<P>(parameters)...)); | 106 return internal::CallClosureWithExecutionContextTask<WTF::CrossThreadAffinit
y>::create(threadSafeBind<ExecutionContext*>(function, std::forward<P>(parameter
s)...)); |
| 135 } | 107 } |
| 136 | 108 |
| 137 // [6] createCrossThreadTask() for member functions + pointers to class C other
than C* or const WeakPtr<C>& | 109 template<typename C, typename... P, typename... MP, |
| 138 // (P = <P0, P1, ..., Pn>, MP = <MP1, ..., MPn>) | |
| 139 template<typename C, typename P0, typename... P, typename... MP, | |
| 140 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> | 110 typename RETTYPE = std::unique_ptr<ExecutionContextTask>, size_t PS = sizeof
...(P), size_t MPS = sizeof...(MP)> |
| 141 typename std::enable_if<PS == MPS && !WTF::IsSubclassOfTemplate<typename std::de
cay<P0>::type, WeakPtr>::value && !std::is_pointer<typename std::decay<P0>::type
>::value, RETTYPE>::type | 111 typename std::enable_if<PS == MPS + 1, RETTYPE>::type createCrossThreadTask(void
(C::*function)(MP...), P&&... parameters) |
| 142 createCrossThreadTask(void (C::*function)(MP...), P0&& parameter0, P&&... parame
ters) | |
| 143 { | 112 { |
| 144 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, std::forward<P0>(parameter0), std::forward<P>(parameters)...)); | 113 return internal::CallClosureTask<WTF::CrossThreadAffinity>::create(threadSaf
eBind(function, std::forward<P>(parameters)...)); |
| 145 } | 114 } |
| 146 | 115 |
| 147 } // namespace blink | 116 } // namespace blink |
| 148 | 117 |
| 149 #endif // CrossThreadTask_h | 118 #endif // CrossThreadTask_h |
| OLD | NEW |