GC constraint solving should be parallel
[WebKit-https.git] / Source / WTF / wtf / SharedTask.h
1 /*
2  * Copyright (C) 2015-2017 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef SharedTask_h
27 #define SharedTask_h
28
29 #include <wtf/Ref.h>
30 #include <wtf/ThreadSafeRefCounted.h>
31
32 namespace WTF {
33
34 // SharedTask is a replacement for std::function for cases where:
35 //
36 // - You'd like to avoid the cost of copying, and would prefer to have reference semantics rather
37 //   than value semantics.
38 // - You want to use FastMalloc rather than system malloc. Note that std::function may avoid malloc
39 //   entirely in some cases, but that's hard to guarantee.
40 // - You intend to share the task with other threads and so want thread-safe reference counting.
41 //
42 // Here's an example of how SharedTask can be better than std::function. If you do:
43 //
44 // std::function<int(double)> a = b;
45 //
46 // Then "a" will get its own copy of all captured by-value variables. The act of copying may
47 // require calls to system malloc, and it may be linear time in the total size of captured
48 // variables. On the other hand, if you do:
49 //
50 // RefPtr<SharedTask<int(double)> a = b;
51 //
52 // Then "a" will point to the same task as b, and the only work involved is the CAS to increase the
53 // reference count.
54 //
55 // Also, SharedTask allows for more flexibility when sharing state between everyone who runs the
56 // task. With std::function, you can only share state using by-reference captured variables.
57 // SharedTask supports this since, like std::function, it can be built from a lambda (see
58 // createSharedTask(), below). But SharedTask also allows you to create your own subclass and put
59 // state in member fields. This can be more natural if you want fine-grained control over what
60 // state is shared between instances of the task.
61 template<typename FunctionType> class SharedTask;
62 template<typename PassedResultType, typename... ArgumentTypes>
63 class SharedTask<PassedResultType (ArgumentTypes...)> : public ThreadSafeRefCounted<SharedTask<PassedResultType (ArgumentTypes...)>> {
64 public:
65     typedef PassedResultType ResultType;
66     
67     SharedTask() { }
68     virtual ~SharedTask() { }
69
70     virtual ResultType run(ArgumentTypes...) = 0;
71 };
72
73 // This is a utility class that allows you to create a SharedTask subclass using a lambda. Usually,
74 // you don't want to use this class directly. Use createSharedTask() instead.
75 template<typename FunctionType, typename Functor> class SharedTaskFunctor;
76 template<typename ResultType, typename... ArgumentTypes, typename Functor>
77 class SharedTaskFunctor<ResultType (ArgumentTypes...), Functor> : public SharedTask<ResultType (ArgumentTypes...)> {
78 public:
79     SharedTaskFunctor(const Functor& functor)
80         : m_functor(functor)
81     {
82     }
83
84     SharedTaskFunctor(Functor&& functor)
85         : m_functor(WTFMove(functor))
86     {
87     }
88
89 private:
90     ResultType run(ArgumentTypes... arguments) override
91     {
92         return m_functor(std::forward<ArgumentTypes>(arguments)...);
93     }
94
95     Functor m_functor;
96 };
97
98 // Create a SharedTask from a functor, such as a lambda. You can use this like so:
99 //
100 // RefPtr<SharedTask<void()>> task = createSharedTask<void()>(
101 //     [=] () {
102 //         do things;
103 //     });
104 //
105 // Note that if you use the [&] capture list, then you're probably doing it wrong. That's because
106 // [&] will lead to pointers to the stack (the only exception is if you do something like &x where
107 // x is a reference to the heap - but in that case, it's better to use [=, &x] to be explicit). You
108 // probably don't want pointers to the stack if you will have tasks running on other threads.
109 // Probably the best way to be sure that you're not making a horrible mistake is to always use
110 // explicit capture lists. In many cases, [this] is sufficient.
111 //
112 // On the other hand, if you use something like ParallelHelperClient::runTaskInParallel() (or its
113 // helper, runFunctionInParallel(), which does createSharedTask() for you), then it can be OK to
114 // use [&], since the stack frame will remain live for the entire duration of the task's lifetime.
115 template<typename FunctionType, typename Functor>
116 Ref<SharedTask<FunctionType>> createSharedTask(const Functor& functor)
117 {
118     return adoptRef(*new SharedTaskFunctor<FunctionType, Functor>(functor));
119 }
120 template<typename FunctionType, typename Functor>
121 Ref<SharedTask<FunctionType>> createSharedTask(Functor&& functor)
122 {
123     return adoptRef(*new SharedTaskFunctor<FunctionType, Functor>(WTFMove(functor)));
124 }
125
126 } // namespace WTF
127
128 using WTF::createSharedTask;
129 using WTF::SharedTask;
130 using WTF::SharedTaskFunctor;
131
132 #endif // SharedTask_h
133