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 |