bind should handle member functions
[WebKit-https.git] / Source / JavaScriptCore / wtf / Functional.h
1 /*
2  * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef WTF_Functional_h
27 #define WTF_Functional_h
28
29 #include "Assertions.h"
30 #include "PassRefPtr.h"
31 #include "RefPtr.h"
32 #include "ThreadSafeRefCounted.h"
33
34 namespace WTF {
35
36 // Functional.h provides a very simple way to bind a function pointer and arguments together into a function object
37 // that can be stored, copied and invoked, similar to how boost::bind and std::bind in C++11.
38 // The implementation is currently very simple, but the goal is to replace WorkItem in WebKit2 and make it easier to
39 // package up and invoke function calls inside WebCore.
40
41 // A FunctionWrapper is a class template that can wrap a function pointer or a member function pointer and
42 // provide a unified interface for calling that function.
43 template<typename> class FunctionWrapper;
44
45 template<typename R> class FunctionWrapper<R (*)()> {
46 public:
47     typedef R ResultType;
48
49     explicit FunctionWrapper(R (*function)())
50         : m_function(function)
51     {
52     }
53
54     R operator()()
55     {
56         return m_function();
57     }
58
59 private:
60     R (*m_function)();
61 };
62
63 template<typename R, typename P0> class FunctionWrapper<R (*)(P0)> {
64 public:
65     typedef R ResultType;
66
67     explicit FunctionWrapper(R (*function)(P0))
68         : m_function(function)
69     {
70     }
71
72     R operator()(P0 p0)
73     {
74         return m_function(p0);
75     }
76
77 private:
78     R (*m_function)(P0);
79 };
80
81 template<typename R, typename P0, typename P1> class FunctionWrapper<R (*)(P0, P1)> {
82 public:
83     typedef R ResultType;
84
85     explicit FunctionWrapper(R (*function)(P0, P1))
86         : m_function(function)
87     {
88     }
89
90     R operator()(P0 p0, P1 p1)
91     {
92         return m_function(p0, p1);
93     }
94
95 private:
96     R (*m_function)(P0, P1);
97 };
98
99 template<typename R, typename C> class FunctionWrapper<R (C::*)()> {
100 public:
101     typedef R ResultType;
102
103     explicit FunctionWrapper(R (C::*function)())
104         : m_function(function)
105     {
106     }
107
108     R operator()(C* c)
109     {
110         return (c->*m_function)();
111     }
112
113 private:
114     R (C::*m_function)();
115 };
116
117 template<typename R, typename C, typename P0> class FunctionWrapper<R (C::*)(P0)> {
118 public:
119     typedef R ResultType;
120
121     explicit FunctionWrapper(R (C::*function)(P0))
122         : m_function(function)
123     {
124     }
125
126     R operator()(C* c, P0 p0)
127     {
128         return (c->*m_function)(p0);
129     }
130
131 private:
132     R (C::*m_function)(P0);
133 };
134
135 class FunctionImplBase : public ThreadSafeRefCounted<FunctionImplBase> {
136 public:
137     virtual ~FunctionImplBase() { }
138 };
139
140 template<typename>
141 class FunctionImpl;
142
143 template<typename R>
144 class FunctionImpl<R ()> : public FunctionImplBase {
145 public:
146     virtual R operator()() = 0;
147 };
148
149 template<typename FunctionWrapper, typename FunctionType>
150 class BoundFunctionImpl;
151
152 template<typename FunctionWrapper> class BoundFunctionImpl<FunctionWrapper, typename FunctionWrapper::ResultType ()> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
153 public:
154     explicit BoundFunctionImpl(FunctionWrapper functionWrapper)
155         : m_functionWrapper(functionWrapper)
156     {
157     }
158
159     virtual typename FunctionWrapper::ResultType operator()()
160     {
161         return m_functionWrapper();
162     }
163
164 private:
165     FunctionWrapper m_functionWrapper;
166 };
167
168 template<typename FunctionWrapper, typename P0> class BoundFunctionImpl<FunctionWrapper, typename FunctionWrapper::ResultType (P0)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
169
170 public:
171     BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0)
172         : m_functionWrapper(functionWrapper)
173         , m_p0(p0)
174     {
175     }
176
177     virtual typename FunctionWrapper::ResultType operator()()
178     {
179         return m_functionWrapper(m_p0);
180     }
181
182 private:
183     FunctionWrapper m_functionWrapper;
184     P0 m_p0;
185 };
186
187 template<typename FunctionWrapper, typename P0, typename P1> class BoundFunctionImpl<FunctionWrapper, typename FunctionWrapper::ResultType (P0, P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
188 public:
189     BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0, const P1& p1)
190         : m_functionWrapper(functionWrapper)
191         , m_p0(p0)
192         , m_p1(p1)
193     {
194     }
195
196     virtual typename FunctionWrapper::ResultType operator()()
197     {
198         return m_functionWrapper(m_p0, m_p1);
199     }
200
201 private:
202     FunctionWrapper m_functionWrapper;
203     P0 m_p0;
204     P1 m_p1;
205 };
206
207 class FunctionBase {
208 public:
209     bool isNull() const
210     {
211         return !m_impl;
212     }
213
214 protected:
215     FunctionBase()
216     {
217     }
218
219     explicit FunctionBase(PassRefPtr<FunctionImplBase> impl)
220         : m_impl(impl)
221     {
222     }
223
224     template<typename FunctionType> FunctionImpl<FunctionType>* impl() const
225     { 
226         return static_cast<FunctionImpl<FunctionType>*>(m_impl.get());
227     }
228
229 private:
230     RefPtr<FunctionImplBase> m_impl;
231 };
232
233 template<typename> class Function;
234
235 template<typename R>
236 class Function<R ()> : public FunctionBase {
237 public:
238     Function()
239     {
240     }
241
242     Function(PassRefPtr<FunctionImpl<R ()> > impl)
243         : FunctionBase(impl)
244     {
245     }
246
247     R operator()()
248     {
249         ASSERT(!isNull());
250
251         return impl<R ()>()->operator()();
252     }
253 };
254
255 template<typename FunctionType>
256 Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function)
257 {
258     return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType ()>(FunctionWrapper<FunctionType>(function))));
259 }
260
261 template<typename FunctionType, typename A1>
262 Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1)
263 {
264     return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1)>(FunctionWrapper<FunctionType>(function), a1)));
265 }
266
267 template<typename FunctionType, typename A1, typename A2>
268 Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2)
269 {
270     return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2)>(FunctionWrapper<FunctionType>(function), a1, a2)));
271 }
272
273 }
274
275 using WTF::Function;
276 using WTF::bind;
277
278 #endif // WTF_Functional_h