1/*
2 * Copyright (C) 2009-2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef CrossThreadTask_h
32#define CrossThreadTask_h
33
34#include "core/dom/ExecutionContext.h"
35#include "core/dom/ExecutionContextTask.h"
36#include "platform/CrossThreadCopier.h"
37#include "wtf/PassOwnPtr.h"
38#include "wtf/PassRefPtr.h"
39#include "wtf/TypeTraits.h"
40
41namespace blink {
42
43// Traits for the CrossThreadTask.
44template<typename T> struct CrossThreadTaskTraits {
45    typedef const T& ParamType;
46};
47
48template<typename T> struct CrossThreadTaskTraits<T*> {
49    typedef T* ParamType;
50};
51
52template<typename T> struct CrossThreadTaskTraits<PassRefPtr<T> > {
53    typedef PassRefPtr<T> ParamType;
54};
55
56template<typename T> struct CrossThreadTaskTraits<PassOwnPtr<T> > {
57    typedef PassOwnPtr<T> ParamType;
58};
59
60// FIXME: Oilpan: Using a RawPtr is not safe, because the RawPtr does not keep
61// the pointee alive while the ExecutionContextTask holds the RawPtr.
62//
63// - Ideally, we want to move the ExecutionContextTask to Oilpan's heap and use a Member.
64// However we cannot do that easily because the ExecutionContextTask outlives the thread
65// that created the ExecutionContextTask. Oilpan does not support objects that
66// outlives the thread that created the objects.
67//
68// - It's not either easy to keep the ExecutionContextTask off-heap
69// and use a Persistent handle. This is because the Persistent handle can cause a cycle.
70// It's possible that the ExecutionContextTask holds a Persistent handle to the object
71// that owns the ExecutionContextTask.
72//
73// Given the above, we cannot avoid using a RawPtr at the moment.
74// It's a responsibility of the caller sites to manage the lifetime of the pointee.
75template<typename T> struct CrossThreadTaskTraits<RawPtr<T> > {
76    typedef RawPtr<T> ParamType;
77};
78
79template<typename P1, typename MP1>
80class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask1 : public ExecutionContextTask {
81public:
82    typedef void (*Method)(ExecutionContext*, MP1);
83    typedef CrossThreadTask1<P1, MP1> CrossThreadTask;
84    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
85
86    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1)
87    {
88        return adoptPtr(new CrossThreadTask(method, parameter1));
89    }
90
91private:
92    CrossThreadTask1(Method method, Param1 parameter1)
93        : m_method(method)
94        , m_parameter1(parameter1)
95    {
96    }
97
98    virtual void performTask(ExecutionContext* context)
99    {
100        (*m_method)(context, m_parameter1);
101    }
102
103private:
104    Method m_method;
105    P1 m_parameter1;
106};
107
108template<typename P1, typename MP1, typename P2, typename MP2>
109class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask2 : public ExecutionContextTask {
110public:
111    typedef void (*Method)(ExecutionContext*, MP1, MP2);
112    typedef CrossThreadTask2<P1, MP1, P2, MP2> CrossThreadTask;
113    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
114    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
115
116    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2)
117    {
118        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2));
119    }
120
121private:
122    CrossThreadTask2(Method method, Param1 parameter1, Param2 parameter2)
123        : m_method(method)
124        , m_parameter1(parameter1)
125        , m_parameter2(parameter2)
126    {
127    }
128
129    virtual void performTask(ExecutionContext* context)
130    {
131        (*m_method)(context, m_parameter1, m_parameter2);
132    }
133
134private:
135    Method m_method;
136    P1 m_parameter1;
137    P2 m_parameter2;
138};
139
140template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
141class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask3 : public ExecutionContextTask {
142public:
143    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3);
144    typedef CrossThreadTask3<P1, MP1, P2, MP2, P3, MP3> CrossThreadTask;
145    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
146    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
147    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
148
149    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
150    {
151        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3));
152    }
153
154private:
155    CrossThreadTask3(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
156        : m_method(method)
157        , m_parameter1(parameter1)
158        , m_parameter2(parameter2)
159        , m_parameter3(parameter3)
160    {
161    }
162
163    virtual void performTask(ExecutionContext* context)
164    {
165        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3);
166    }
167
168private:
169    Method m_method;
170    P1 m_parameter1;
171    P2 m_parameter2;
172    P3 m_parameter3;
173};
174
175template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
176class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask4 : public ExecutionContextTask {
177public:
178    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3, MP4);
179    typedef CrossThreadTask4<P1, MP1, P2, MP2, P3, MP3, P4, MP4> CrossThreadTask;
180    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
181    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
182    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
183    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
184
185    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
186    {
187        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4));
188    }
189
190private:
191    CrossThreadTask4(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
192        : m_method(method)
193        , m_parameter1(parameter1)
194        , m_parameter2(parameter2)
195        , m_parameter3(parameter3)
196        , m_parameter4(parameter4)
197    {
198    }
199
200    virtual void performTask(ExecutionContext* context)
201    {
202        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4);
203    }
204
205private:
206    Method m_method;
207    P1 m_parameter1;
208    P2 m_parameter2;
209    P3 m_parameter3;
210    P4 m_parameter4;
211};
212
213template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
214class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask5 : public ExecutionContextTask {
215public:
216    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5);
217    typedef CrossThreadTask5<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5> CrossThreadTask;
218    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
219    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
220    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
221    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
222    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
223
224    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
225    {
226        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5));
227    }
228
229private:
230    CrossThreadTask5(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5)
231        : m_method(method)
232        , m_parameter1(parameter1)
233        , m_parameter2(parameter2)
234        , m_parameter3(parameter3)
235        , m_parameter4(parameter4)
236        , m_parameter5(parameter5)
237    {
238    }
239
240    virtual void performTask(ExecutionContext* context)
241    {
242        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5);
243    }
244
245private:
246    Method m_method;
247    P1 m_parameter1;
248    P2 m_parameter2;
249    P3 m_parameter3;
250    P4 m_parameter4;
251    P5 m_parameter5;
252};
253
254template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
255class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask6 : public ExecutionContextTask {
256public:
257    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6);
258    typedef CrossThreadTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6> CrossThreadTask;
259    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
260    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
261    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
262    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
263    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
264    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
265
266    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
267    {
268        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6));
269    }
270
271private:
272    CrossThreadTask6(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6)
273        : m_method(method)
274        , m_parameter1(parameter1)
275        , m_parameter2(parameter2)
276        , m_parameter3(parameter3)
277        , m_parameter4(parameter4)
278        , m_parameter5(parameter5)
279        , m_parameter6(parameter6)
280    {
281    }
282
283    virtual void performTask(ExecutionContext* context)
284    {
285        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6);
286    }
287
288private:
289    Method m_method;
290    P1 m_parameter1;
291    P2 m_parameter2;
292    P3 m_parameter3;
293    P4 m_parameter4;
294    P5 m_parameter5;
295    P6 m_parameter6;
296};
297
298template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
299class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask7 : public ExecutionContextTask {
300public:
301    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7);
302    typedef CrossThreadTask7<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6, P7, MP7> CrossThreadTask;
303    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
304    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
305    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
306    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
307    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
308    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
309    typedef typename CrossThreadTaskTraits<P7>::ParamType Param7;
310
311    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
312    {
313        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7));
314    }
315
316private:
317    CrossThreadTask7(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7)
318        : m_method(method)
319        , m_parameter1(parameter1)
320        , m_parameter2(parameter2)
321        , m_parameter3(parameter3)
322        , m_parameter4(parameter4)
323        , m_parameter5(parameter5)
324        , m_parameter6(parameter6)
325        , m_parameter7(parameter7)
326    {
327    }
328
329    virtual void performTask(ExecutionContext* context)
330    {
331        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6, m_parameter7);
332    }
333
334private:
335    Method m_method;
336    P1 m_parameter1;
337    P2 m_parameter2;
338    P3 m_parameter3;
339    P4 m_parameter4;
340    P5 m_parameter5;
341    P6 m_parameter6;
342    P7 m_parameter7;
343};
344
345template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7, typename P8, typename MP8>
346class GC_PLUGIN_IGNORE("crbug.com/378192") CrossThreadTask8 : public ExecutionContextTask {
347public:
348    typedef void (*Method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8);
349    typedef CrossThreadTask8<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6, P7, MP7, P8, MP8> CrossThreadTask;
350    typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
351    typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
352    typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
353    typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
354    typedef typename CrossThreadTaskTraits<P5>::ParamType Param5;
355    typedef typename CrossThreadTaskTraits<P6>::ParamType Param6;
356    typedef typename CrossThreadTaskTraits<P7>::ParamType Param7;
357    typedef typename CrossThreadTaskTraits<P8>::ParamType Param8;
358
359    static PassOwnPtr<CrossThreadTask> create(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7, Param8 parameter8)
360    {
361        return adoptPtr(new CrossThreadTask(method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8));
362    }
363
364private:
365    CrossThreadTask8(Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4, Param5 parameter5, Param6 parameter6, Param7 parameter7, Param8 parameter8)
366    : m_method(method)
367    , m_parameter1(parameter1)
368    , m_parameter2(parameter2)
369    , m_parameter3(parameter3)
370    , m_parameter4(parameter4)
371    , m_parameter5(parameter5)
372    , m_parameter6(parameter6)
373    , m_parameter7(parameter7)
374    , m_parameter8(parameter8)
375    {
376    }
377
378    virtual void performTask(ExecutionContext* context)
379    {
380        (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6, m_parameter7, m_parameter8);
381    }
382
383private:
384    Method m_method;
385    P1 m_parameter1;
386    P2 m_parameter2;
387    P3 m_parameter3;
388    P4 m_parameter4;
389    P5 m_parameter5;
390    P6 m_parameter6;
391    P7 m_parameter7;
392    P8 m_parameter8;
393};
394
395template<typename P1, typename MP1>
396PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
397    void (*method)(ExecutionContext*, MP1),
398    const P1& parameter1)
399{
400    return CrossThreadTask1<typename CrossThreadCopier<P1>::Type, MP1>::create(
401        method,
402        CrossThreadCopier<P1>::copy(parameter1));
403}
404
405template<typename P1, typename MP1, typename P2, typename MP2>
406PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
407    void (*method)(ExecutionContext*, MP1, MP2),
408    const P1& parameter1, const P2& parameter2)
409{
410    return CrossThreadTask2<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
411        method,
412        CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2));
413}
414
415template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
416PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
417    void (*method)(ExecutionContext*, MP1, MP2, MP3),
418    const P1& parameter1, const P2& parameter2, const P3& parameter3)
419{
420    return CrossThreadTask3<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
421        method,
422        CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
423        CrossThreadCopier<P3>::copy(parameter3));
424}
425
426template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
427PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
428    void (*method)(ExecutionContext*, MP1, MP2, MP3, MP4),
429    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
430{
431    return CrossThreadTask4<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
432        typename CrossThreadCopier<P4>::Type, MP4>::create(
433            method,
434            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
435            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4));
436}
437
438template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
439PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
440    void (*method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5),
441    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
442{
443    return CrossThreadTask5<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
444        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5>::create(
445            method,
446            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
447            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
448            CrossThreadCopier<P5>::copy(parameter5));
449}
450
451template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6>
452PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
453    void (*method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6),
454    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6)
455{
456    return CrossThreadTask6<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
457        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6>::create(
458            method,
459            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
460            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
461            CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6));
462}
463
464template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7>
465PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
466    void (*method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7),
467    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6, const P7& parameter7)
468{
469    return CrossThreadTask7<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
470        typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6,
471        typename CrossThreadCopier<P7>::Type, MP7>::create(
472            method,
473            CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
474            CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
475            CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6),
476            CrossThreadCopier<P7>::copy(parameter7));
477}
478
479template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7, typename P8, typename MP8>
480PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
481    void (*method)(ExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8),
482    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6, const P7& parameter7, const P8& parameter8)
483{
484    return CrossThreadTask8<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3,
485    typename CrossThreadCopier<P4>::Type, MP4, typename CrossThreadCopier<P5>::Type, MP5, typename CrossThreadCopier<P6>::Type, MP6,
486    typename CrossThreadCopier<P7>::Type, MP7, typename CrossThreadCopier<P8>::Type, MP8>::create(
487                                                       method,
488                                                       CrossThreadCopier<P1>::copy(parameter1), CrossThreadCopier<P2>::copy(parameter2),
489                                                       CrossThreadCopier<P3>::copy(parameter3), CrossThreadCopier<P4>::copy(parameter4),
490                                                       CrossThreadCopier<P5>::copy(parameter5), CrossThreadCopier<P6>::copy(parameter6),
491                                                       CrossThreadCopier<P7>::copy(parameter7), CrossThreadCopier<P8>::copy(parameter8));
492}
493
494// createCrossThreadTask(...) is similar to but safer than
495// CallClosureTask::create(bind(...)) for cross-thread task posting.
496// postTask(CallClosureTask::create(bind(...))) is not thread-safe
497// due to temporary objects, see http://crbug.com/390851 for details.
498//
499// createCrossThreadTask copies its arguments into Closure
500// by CrossThreadCopier, rather than copy constructors.
501// This means it creates deep copy of each argument if necessary.
502//
503// To pass things that cannot be copied by CrossThreadCopier
504// (e.g. pointers), use AllowCrossThreadAccess() explicitly.
505//
506// If the first argument of createCrossThreadTask
507// is a pointer to a member function in class C,
508// then the second argument of createCrossThreadTask
509// is a raw pointer (C*) or a weak pointer (const WeakPtr<C>&) to C.
510// createCrossThreadTask does not use CrossThreadCopier for the pointer,
511// assuming the user of createCrossThreadTask knows that the pointer
512// can be accessed from the target thread.
513
514// Templates for member function of class C + raw pointer (C*)
515// which do not use CrossThreadCopier for the raw pointer (a1)
516template<typename C>
517PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
518    void (C::*function)(),
519    C* p)
520{
521    return CallClosureTask::create(bind(function,
522        p));
523}
524
525template<typename C, typename P1, typename MP1>
526PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
527    void (C::*function)(MP1),
528    C* p, const P1& parameter1)
529{
530    return CallClosureTask::create(bind(function,
531        p,
532        CrossThreadCopier<P1>::copy(parameter1)));
533}
534
535template<typename C, typename P1, typename MP1, typename P2, typename MP2>
536PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
537    void (C::*function)(MP1, MP2),
538    C* p, const P1& parameter1, const P2& parameter2)
539{
540    return CallClosureTask::create(bind(function,
541        p,
542        CrossThreadCopier<P1>::copy(parameter1),
543        CrossThreadCopier<P2>::copy(parameter2)));
544}
545
546template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
547PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
548    void (C::*function)(MP1, MP2, MP3),
549    C* p, const P1& parameter1, const P2& parameter2, const P3& parameter3)
550{
551    return CallClosureTask::create(bind(function,
552        p,
553        CrossThreadCopier<P1>::copy(parameter1),
554        CrossThreadCopier<P2>::copy(parameter2),
555        CrossThreadCopier<P3>::copy(parameter3)));
556}
557
558template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
559PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
560    void (C::*function)(MP1, MP2, MP3, MP4),
561    C* p, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
562{
563    return CallClosureTask::create(bind(function,
564        p,
565        CrossThreadCopier<P1>::copy(parameter1),
566        CrossThreadCopier<P2>::copy(parameter2),
567        CrossThreadCopier<P3>::copy(parameter3),
568        CrossThreadCopier<P4>::copy(parameter4)));
569}
570
571template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
572PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
573    void (C::*function)(MP1, MP2, MP3, MP4, MP5),
574    C* p, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
575{
576    return CallClosureTask::create(bind(function,
577        p,
578        CrossThreadCopier<P1>::copy(parameter1),
579        CrossThreadCopier<P2>::copy(parameter2),
580        CrossThreadCopier<P3>::copy(parameter3),
581        CrossThreadCopier<P4>::copy(parameter4),
582        CrossThreadCopier<P5>::copy(parameter5)));
583}
584
585// Templates for member function of class C + weak pointer (const WeakPtr<C>&)
586// which do not use CrossThreadCopier for the weak pointer (a1)
587template<typename C>
588PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
589    void (C::*function)(),
590    const WeakPtr<C>& p)
591{
592    return CallClosureTask::create(bind(function,
593        p));
594}
595
596template<typename C, typename P1, typename MP1>
597PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
598    void (C::*function)(MP1),
599    const WeakPtr<C>& p, const P1& parameter1)
600{
601    return CallClosureTask::create(bind(function,
602        p,
603        CrossThreadCopier<P1>::copy(parameter1)));
604}
605
606template<typename C, typename P1, typename MP1, typename P2, typename MP2>
607PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
608    void (C::*function)(MP1, MP2),
609    const WeakPtr<C>& p, const P1& parameter1, const P2& parameter2)
610{
611    return CallClosureTask::create(bind(function,
612        p,
613        CrossThreadCopier<P1>::copy(parameter1),
614        CrossThreadCopier<P2>::copy(parameter2)));
615}
616
617template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
618PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
619    void (C::*function)(MP1, MP2, MP3),
620    const WeakPtr<C>& p, const P1& parameter1, const P2& parameter2, const P3& parameter3)
621{
622    return CallClosureTask::create(bind(function,
623        p,
624        CrossThreadCopier<P1>::copy(parameter1),
625        CrossThreadCopier<P2>::copy(parameter2),
626        CrossThreadCopier<P3>::copy(parameter3)));
627}
628
629template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
630PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
631    void (C::*function)(MP1, MP2, MP3, MP4),
632    const WeakPtr<C>& p, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
633{
634    return CallClosureTask::create(bind(function,
635        p,
636        CrossThreadCopier<P1>::copy(parameter1),
637        CrossThreadCopier<P2>::copy(parameter2),
638        CrossThreadCopier<P3>::copy(parameter3),
639        CrossThreadCopier<P4>::copy(parameter4)));
640}
641
642template<typename C, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5>
643PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
644    void (C::*function)(MP1, MP2, MP3, MP4, MP5),
645    const WeakPtr<C>& p, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
646{
647    return CallClosureTask::create(bind(function,
648        p,
649        CrossThreadCopier<P1>::copy(parameter1),
650        CrossThreadCopier<P2>::copy(parameter2),
651        CrossThreadCopier<P3>::copy(parameter3),
652        CrossThreadCopier<P4>::copy(parameter4),
653        CrossThreadCopier<P5>::copy(parameter5)));
654}
655
656// Other cases; use CrossThreadCopier for all arguments
657template<typename FunctionType>
658PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
659    FunctionType function)
660{
661    return CallClosureTask::create(bind(function));
662}
663
664template<typename FunctionType, typename P1>
665PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
666    FunctionType function,
667    const P1& parameter1)
668{
669    return CallClosureTask::create(bind(function,
670        CrossThreadCopier<P1>::copy(parameter1)));
671}
672
673template<typename FunctionType, typename P1, typename P2>
674PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
675    FunctionType function,
676    const P1& parameter1, const P2& parameter2)
677{
678    return CallClosureTask::create(bind(function,
679        CrossThreadCopier<P1>::copy(parameter1),
680        CrossThreadCopier<P2>::copy(parameter2)));
681}
682
683template<typename FunctionType, typename P1, typename P2, typename P3>
684PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
685    FunctionType function,
686    const P1& parameter1, const P2& parameter2, const P3& parameter3)
687{
688    return CallClosureTask::create(bind(function,
689        CrossThreadCopier<P1>::copy(parameter1),
690        CrossThreadCopier<P2>::copy(parameter2),
691        CrossThreadCopier<P3>::copy(parameter3)));
692}
693
694template<typename FunctionType, typename P1, typename P2, typename P3, typename P4>
695PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
696    FunctionType function,
697    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
698{
699    return CallClosureTask::create(bind(function,
700        CrossThreadCopier<P1>::copy(parameter1),
701        CrossThreadCopier<P2>::copy(parameter2),
702        CrossThreadCopier<P3>::copy(parameter3),
703        CrossThreadCopier<P4>::copy(parameter4)));
704}
705
706template<typename FunctionType, typename P1, typename P2, typename P3, typename P4, typename P5>
707PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
708    FunctionType function,
709    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
710{
711    return CallClosureTask::create(bind(function,
712        CrossThreadCopier<P1>::copy(parameter1),
713        CrossThreadCopier<P2>::copy(parameter2),
714        CrossThreadCopier<P3>::copy(parameter3),
715        CrossThreadCopier<P4>::copy(parameter4),
716        CrossThreadCopier<P5>::copy(parameter5)));
717}
718
719template<typename FunctionType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
720PassOwnPtr<ExecutionContextTask> createCrossThreadTask(
721    FunctionType function,
722    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6)
723{
724    return CallClosureTask::create(bind(function,
725        CrossThreadCopier<P1>::copy(parameter1),
726        CrossThreadCopier<P2>::copy(parameter2),
727        CrossThreadCopier<P3>::copy(parameter3),
728        CrossThreadCopier<P4>::copy(parameter4),
729        CrossThreadCopier<P5>::copy(parameter5),
730        CrossThreadCopier<P6>::copy(parameter6)));
731}
732
733} // namespace blink
734
735#endif // CrossThreadTask_h
736