1/*
2 * Copyright (C) 2013 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 *     * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef ExecutionContextTask_h
28#define ExecutionContextTask_h
29
30#include "wtf/FastAllocBase.h"
31#include "wtf/Functional.h"
32#include "wtf/Noncopyable.h"
33#include "wtf/PassOwnPtr.h"
34#include "wtf/text/WTFString.h"
35
36namespace blink {
37
38class ExecutionContext;
39
40class ExecutionContextTask {
41    WTF_MAKE_NONCOPYABLE(ExecutionContextTask);
42    WTF_MAKE_FAST_ALLOCATED;
43public:
44    ExecutionContextTask() { }
45    virtual ~ExecutionContextTask() { }
46    virtual void performTask(ExecutionContext*) = 0;
47    // Certain tasks get marked specially so that they aren't discarded, and are executed, when the context is shutting down its message queue.
48    virtual bool isCleanupTask() const { return false; }
49    virtual const String& taskNameForInstrumentation() const { return emptyString(); }
50};
51
52class CallClosureTask FINAL : public ExecutionContextTask {
53public:
54    // Do not use |create| other than in createCrossThreadTask and
55    // createSameThreadTask.
56    // See http://crbug.com/390851
57    static PassOwnPtr<CallClosureTask> create(const Closure& closure)
58    {
59        return adoptPtr(new CallClosureTask(closure));
60    }
61    virtual void performTask(ExecutionContext*) OVERRIDE { m_closure(); }
62
63private:
64    explicit CallClosureTask(const Closure& closure) : m_closure(closure) { }
65    Closure m_closure;
66};
67
68// Create tasks passed within a single thread.
69// When posting tasks within a thread, use |createSameThreadTask| instead
70// of using |bind| directly to state explicitly that there is no need to care
71// about thread safety when posting the task.
72// When posting tasks across threads, use |createCrossThreadTask|.
73template<typename FunctionType>
74PassOwnPtr<ExecutionContextTask> createSameThreadTask(
75    FunctionType function)
76{
77    return CallClosureTask::create(bind(function));
78}
79
80template<typename FunctionType, typename P1>
81PassOwnPtr<ExecutionContextTask> createSameThreadTask(
82    FunctionType function,
83    const P1& parameter1)
84{
85    return CallClosureTask::create(bind(function,
86        parameter1));
87}
88
89template<typename FunctionType, typename P1, typename P2>
90PassOwnPtr<ExecutionContextTask> createSameThreadTask(
91    FunctionType function,
92    const P1& parameter1, const P2& parameter2)
93{
94    return CallClosureTask::create(bind(function,
95        parameter1,
96        parameter2));
97}
98
99template<typename FunctionType, typename P1, typename P2, typename P3>
100PassOwnPtr<ExecutionContextTask> createSameThreadTask(
101    FunctionType function,
102    const P1& parameter1, const P2& parameter2, const P3& parameter3)
103{
104    return CallClosureTask::create(bind(function,
105        parameter1,
106        parameter2,
107        parameter3));
108}
109
110template<typename FunctionType, typename P1, typename P2, typename P3, typename P4>
111PassOwnPtr<ExecutionContextTask> createSameThreadTask(
112    FunctionType function,
113    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4)
114{
115    return CallClosureTask::create(bind(function,
116        parameter1,
117        parameter2,
118        parameter3,
119        parameter4));
120}
121
122template<typename FunctionType, typename P1, typename P2, typename P3, typename P4, typename P5>
123PassOwnPtr<ExecutionContextTask> createSameThreadTask(
124    FunctionType function,
125    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5)
126{
127    return CallClosureTask::create(bind(function,
128        parameter1,
129        parameter2,
130        parameter3,
131        parameter4,
132        parameter5));
133}
134
135template<typename FunctionType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
136PassOwnPtr<ExecutionContextTask> createSameThreadTask(
137    FunctionType function,
138    const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6)
139{
140    return CallClosureTask::create(bind(function,
141        parameter1,
142        parameter2,
143        parameter3,
144        parameter4,
145        parameter5,
146        parameter6));
147}
148
149} // namespace
150
151#endif
152