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 "wtf/Assertions.h"
30#include "wtf/PassRefPtr.h"
31#include "wtf/RefPtr.h"
32#include "wtf/ThreadSafeRefCounted.h"
33#include "wtf/WeakPtr.h"
34
35namespace WTF {
36
37// Functional.h provides a very simple way to bind a function pointer and arguments together into a function object
38// that can be stored, copied and invoked, similar to how boost::bind and std::bind in C++11.
39
40// A FunctionWrapper is a class template that can wrap a function pointer or a member function pointer and
41// provide a unified interface for calling that function.
42template<typename>
43class FunctionWrapper;
44
45// Bound static functions:
46
47template<typename R>
48class FunctionWrapper<R (*)()> {
49public:
50    typedef R ResultType;
51
52    explicit FunctionWrapper(R (*function)())
53        : m_function(function)
54    {
55    }
56
57    R operator()()
58    {
59        return m_function();
60    }
61
62private:
63    R (*m_function)();
64};
65
66template<typename R, typename P1>
67class FunctionWrapper<R (*)(P1)> {
68public:
69    typedef R ResultType;
70
71    explicit FunctionWrapper(R (*function)(P1))
72        : m_function(function)
73    {
74    }
75
76    R operator()(P1 p1)
77    {
78        return m_function(p1);
79    }
80
81private:
82    R (*m_function)(P1);
83};
84
85template<typename R, typename P1, typename P2>
86class FunctionWrapper<R (*)(P1, P2)> {
87public:
88    typedef R ResultType;
89
90    explicit FunctionWrapper(R (*function)(P1, P2))
91        : m_function(function)
92    {
93    }
94
95    R operator()(P1 p1, P2 p2)
96    {
97        return m_function(p1, p2);
98    }
99
100private:
101    R (*m_function)(P1, P2);
102};
103
104template<typename R, typename P1, typename P2, typename P3>
105class FunctionWrapper<R (*)(P1, P2, P3)> {
106public:
107    typedef R ResultType;
108
109    explicit FunctionWrapper(R (*function)(P1, P2, P3))
110        : m_function(function)
111    {
112    }
113
114    R operator()(P1 p1, P2 p2, P3 p3)
115    {
116        return m_function(p1, p2, p3);
117    }
118
119private:
120    R (*m_function)(P1, P2, P3);
121};
122
123template<typename R, typename P1, typename P2, typename P3, typename P4>
124class FunctionWrapper<R (*)(P1, P2, P3, P4)> {
125public:
126    typedef R ResultType;
127
128    explicit FunctionWrapper(R (*function)(P1, P2, P3, P4))
129        : m_function(function)
130    {
131    }
132
133    R operator()(P1 p1, P2 p2, P3 p3, P4 p4)
134    {
135        return m_function(p1, p2, p3, p4);
136    }
137
138private:
139    R (*m_function)(P1, P2, P3, P4);
140};
141
142template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
143class FunctionWrapper<R (*)(P1, P2, P3, P4, P5)> {
144public:
145    typedef R ResultType;
146
147    explicit FunctionWrapper(R (*function)(P1, P2, P3, P4, P5))
148        : m_function(function)
149    {
150    }
151
152    R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
153    {
154        return m_function(p1, p2, p3, p4, p5);
155    }
156
157private:
158    R (*m_function)(P1, P2, P3, P4, P5);
159};
160
161// Bound member functions:
162
163template<typename R, typename C>
164class FunctionWrapper<R (C::*)()> {
165public:
166    typedef R ResultType;
167
168    explicit FunctionWrapper(R (C::*function)())
169        : m_function(function)
170    {
171    }
172
173    R operator()(C* c)
174    {
175        return (c->*m_function)();
176    }
177
178    R operator()(const WeakPtr<C>& c)
179    {
180        C* obj = c.get();
181        if (!obj)
182            return R();
183        return (obj->*m_function)();
184    }
185
186private:
187    R (C::*m_function)();
188};
189
190template<typename R, typename C, typename P1>
191class FunctionWrapper<R (C::*)(P1)> {
192public:
193    typedef R ResultType;
194
195    explicit FunctionWrapper(R (C::*function)(P1))
196        : m_function(function)
197    {
198    }
199
200    R operator()(C* c, P1 p1)
201    {
202        return (c->*m_function)(p1);
203    }
204
205    R operator()(const WeakPtr<C>& c, P1 p1)
206    {
207        C* obj = c.get();
208        if (!obj)
209            return R();
210        return (obj->*m_function)(p1);
211    }
212
213private:
214    R (C::*m_function)(P1);
215};
216
217template<typename R, typename C, typename P1, typename P2>
218class FunctionWrapper<R (C::*)(P1, P2)> {
219public:
220    typedef R ResultType;
221
222    explicit FunctionWrapper(R (C::*function)(P1, P2))
223        : m_function(function)
224    {
225    }
226
227    R operator()(C* c, P1 p1, P2 p2)
228    {
229        return (c->*m_function)(p1, p2);
230    }
231
232    R operator()(const WeakPtr<C>& c, P1 p1, P2 p2)
233    {
234        C* obj = c.get();
235        if (!obj)
236            return R();
237        return (obj->*m_function)(p1, p2);
238    }
239
240private:
241    R (C::*m_function)(P1, P2);
242};
243
244template<typename R, typename C, typename P1, typename P2, typename P3>
245class FunctionWrapper<R (C::*)(P1, P2, P3)> {
246public:
247    typedef R ResultType;
248
249    explicit FunctionWrapper(R (C::*function)(P1, P2, P3))
250        : m_function(function)
251    {
252    }
253
254    R operator()(C* c, P1 p1, P2 p2, P3 p3)
255    {
256        return (c->*m_function)(p1, p2, p3);
257    }
258
259    R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3)
260    {
261        C* obj = c.get();
262        if (!obj)
263            return R();
264        return (obj->*m_function)(p1, p2, p3);
265    }
266
267private:
268    R (C::*m_function)(P1, P2, P3);
269};
270
271template<typename R, typename C, typename P1, typename P2, typename P3, typename P4>
272class FunctionWrapper<R (C::*)(P1, P2, P3, P4)> {
273public:
274    typedef R ResultType;
275
276    explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4))
277        : m_function(function)
278    {
279    }
280
281    R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4)
282    {
283        return (c->*m_function)(p1, p2, p3, p4);
284    }
285
286    R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3, P4 p4)
287    {
288        C* obj = c.get();
289        if (!obj)
290            return R();
291        return (obj->*m_function)(p1, p2, p3, p4);
292    }
293
294private:
295    R (C::*m_function)(P1, P2, P3, P4);
296};
297
298template<typename R, typename C, typename P1, typename P2, typename P3, typename P4, typename P5>
299class FunctionWrapper<R (C::*)(P1, P2, P3, P4, P5)> {
300public:
301    typedef R ResultType;
302
303    explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4, P5))
304        : m_function(function)
305    {
306    }
307
308    R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
309    {
310        return (c->*m_function)(p1, p2, p3, p4, p5);
311    }
312
313    R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
314    {
315        C* obj = c.get();
316        if (!obj)
317            return R();
318        return (obj->*m_function)(p1, p2, p3, p4, p5);
319    }
320
321private:
322    R (C::*m_function)(P1, P2, P3, P4, P5);
323};
324
325template<typename T> struct ParamStorageTraits {
326    typedef T StorageType;
327
328    static StorageType wrap(const T& value) { return value; }
329    static const T& unwrap(const StorageType& value) { return value; }
330};
331
332template<typename T> struct ParamStorageTraits<PassRefPtr<T> > {
333    typedef RefPtr<T> StorageType;
334
335    static StorageType wrap(PassRefPtr<T> value) { return value; }
336    static T* unwrap(const StorageType& value) { return value.get(); }
337};
338
339template<typename T> struct ParamStorageTraits<RefPtr<T> > {
340    typedef RefPtr<T> StorageType;
341
342    static StorageType wrap(RefPtr<T> value) { return value.release(); }
343    static T* unwrap(const StorageType& value) { return value.get(); }
344};
345
346template<typename> class RetainPtr;
347
348template<typename T> struct ParamStorageTraits<RetainPtr<T> > {
349    typedef RetainPtr<T> StorageType;
350
351    static StorageType wrap(const RetainPtr<T>& value) { return value; }
352    static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { return value.get(); }
353};
354
355class FunctionImplBase : public ThreadSafeRefCounted<FunctionImplBase> {
356public:
357    virtual ~FunctionImplBase() { }
358};
359
360template<typename>
361class FunctionImpl;
362
363template<typename R>
364class FunctionImpl<R ()> : public FunctionImplBase {
365public:
366    virtual R operator()() = 0;
367};
368
369template<typename FunctionWrapper, typename FunctionType>
370class BoundFunctionImpl;
371
372template<typename FunctionWrapper, typename R>
373class BoundFunctionImpl<FunctionWrapper, R ()> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
374public:
375    explicit BoundFunctionImpl(FunctionWrapper functionWrapper)
376        : m_functionWrapper(functionWrapper)
377    {
378    }
379
380    virtual typename FunctionWrapper::ResultType operator()()
381    {
382        return m_functionWrapper();
383    }
384
385private:
386    FunctionWrapper m_functionWrapper;
387};
388
389template<typename FunctionWrapper, typename R, typename P1>
390class BoundFunctionImpl<FunctionWrapper, R (P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
391public:
392    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1)
393        : m_functionWrapper(functionWrapper)
394        , m_p1(ParamStorageTraits<P1>::wrap(p1))
395    {
396    }
397
398    virtual typename FunctionWrapper::ResultType operator()()
399    {
400        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1));
401    }
402
403private:
404    FunctionWrapper m_functionWrapper;
405    typename ParamStorageTraits<P1>::StorageType m_p1;
406};
407
408template<typename FunctionWrapper, typename R, typename P1, typename P2>
409class BoundFunctionImpl<FunctionWrapper, R (P1, P2)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
410public:
411    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2)
412        : m_functionWrapper(functionWrapper)
413        , m_p1(ParamStorageTraits<P1>::wrap(p1))
414        , m_p2(ParamStorageTraits<P2>::wrap(p2))
415    {
416    }
417
418    virtual typename FunctionWrapper::ResultType operator()()
419    {
420        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2));
421    }
422
423private:
424    FunctionWrapper m_functionWrapper;
425    typename ParamStorageTraits<P1>::StorageType m_p1;
426    typename ParamStorageTraits<P2>::StorageType m_p2;
427};
428
429template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3>
430class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
431public:
432    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3)
433        : m_functionWrapper(functionWrapper)
434        , m_p1(ParamStorageTraits<P1>::wrap(p1))
435        , m_p2(ParamStorageTraits<P2>::wrap(p2))
436        , m_p3(ParamStorageTraits<P3>::wrap(p3))
437    {
438    }
439
440    virtual typename FunctionWrapper::ResultType operator()()
441    {
442        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3));
443    }
444
445private:
446    FunctionWrapper m_functionWrapper;
447    typename ParamStorageTraits<P1>::StorageType m_p1;
448    typename ParamStorageTraits<P2>::StorageType m_p2;
449    typename ParamStorageTraits<P3>::StorageType m_p3;
450};
451
452template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4>
453class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
454public:
455    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4)
456        : m_functionWrapper(functionWrapper)
457        , m_p1(ParamStorageTraits<P1>::wrap(p1))
458        , m_p2(ParamStorageTraits<P2>::wrap(p2))
459        , m_p3(ParamStorageTraits<P3>::wrap(p3))
460        , m_p4(ParamStorageTraits<P4>::wrap(p4))
461    {
462    }
463
464    virtual typename FunctionWrapper::ResultType operator()()
465    {
466        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4));
467    }
468
469private:
470    FunctionWrapper m_functionWrapper;
471    typename ParamStorageTraits<P1>::StorageType m_p1;
472    typename ParamStorageTraits<P2>::StorageType m_p2;
473    typename ParamStorageTraits<P3>::StorageType m_p3;
474    typename ParamStorageTraits<P4>::StorageType m_p4;
475};
476
477template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
478class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4, P5)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
479public:
480    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5)
481        : m_functionWrapper(functionWrapper)
482        , m_p1(ParamStorageTraits<P1>::wrap(p1))
483        , m_p2(ParamStorageTraits<P2>::wrap(p2))
484        , m_p3(ParamStorageTraits<P3>::wrap(p3))
485        , m_p4(ParamStorageTraits<P4>::wrap(p4))
486        , m_p5(ParamStorageTraits<P5>::wrap(p5))
487    {
488    }
489
490    virtual typename FunctionWrapper::ResultType operator()()
491    {
492        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5));
493    }
494
495private:
496    FunctionWrapper m_functionWrapper;
497    typename ParamStorageTraits<P1>::StorageType m_p1;
498    typename ParamStorageTraits<P2>::StorageType m_p2;
499    typename ParamStorageTraits<P3>::StorageType m_p3;
500    typename ParamStorageTraits<P4>::StorageType m_p4;
501    typename ParamStorageTraits<P5>::StorageType m_p5;
502};
503
504template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
505class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4, P5, P6)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
506public:
507    BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6)
508        : m_functionWrapper(functionWrapper)
509        , m_p1(ParamStorageTraits<P1>::wrap(p1))
510        , m_p2(ParamStorageTraits<P2>::wrap(p2))
511        , m_p3(ParamStorageTraits<P3>::wrap(p3))
512        , m_p4(ParamStorageTraits<P4>::wrap(p4))
513        , m_p5(ParamStorageTraits<P5>::wrap(p5))
514        , m_p6(ParamStorageTraits<P6>::wrap(p6))
515    {
516    }
517
518    virtual typename FunctionWrapper::ResultType operator()()
519    {
520        return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5), ParamStorageTraits<P6>::unwrap(m_p6));
521    }
522
523private:
524    FunctionWrapper m_functionWrapper;
525    typename ParamStorageTraits<P1>::StorageType m_p1;
526    typename ParamStorageTraits<P2>::StorageType m_p2;
527    typename ParamStorageTraits<P3>::StorageType m_p3;
528    typename ParamStorageTraits<P4>::StorageType m_p4;
529    typename ParamStorageTraits<P5>::StorageType m_p5;
530    typename ParamStorageTraits<P6>::StorageType m_p6;
531};
532
533class FunctionBase {
534public:
535    bool isNull() const
536    {
537        return !m_impl;
538    }
539
540protected:
541    FunctionBase()
542    {
543    }
544
545    explicit FunctionBase(PassRefPtr<FunctionImplBase> impl)
546        : m_impl(impl)
547    {
548    }
549
550    template<typename FunctionType> FunctionImpl<FunctionType>* impl() const
551    {
552        return static_cast<FunctionImpl<FunctionType>*>(m_impl.get());
553    }
554
555private:
556    RefPtr<FunctionImplBase> m_impl;
557};
558
559template<typename>
560class Function;
561
562template<typename R>
563class Function<R ()> : public FunctionBase {
564public:
565    Function()
566    {
567    }
568
569    Function(PassRefPtr<FunctionImpl<R ()> > impl)
570        : FunctionBase(impl)
571    {
572    }
573
574    R operator()() const
575    {
576        ASSERT(!isNull());
577        return impl<R ()>()->operator()();
578    }
579};
580
581template<typename FunctionType>
582Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function)
583{
584    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType ()>(FunctionWrapper<FunctionType>(function))));
585}
586
587template<typename FunctionType, typename A1>
588Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1)
589{
590    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1)>(FunctionWrapper<FunctionType>(function), a1)));
591}
592
593template<typename FunctionType, typename A1, typename A2>
594Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2)
595{
596    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2)>(FunctionWrapper<FunctionType>(function), a1, a2)));
597}
598
599template<typename FunctionType, typename A1, typename A2, typename A3>
600Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3)
601{
602    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3)>(FunctionWrapper<FunctionType>(function), a1, a2, a3)));
603}
604
605template<typename FunctionType, typename A1, typename A2, typename A3, typename A4>
606Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4)
607{
608    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4)));
609}
610
611template<typename FunctionType, typename A1, typename A2, typename A3, typename A4, typename A5>
612Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5)
613{
614    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4, A5)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4, a5)));
615}
616
617template<typename FunctionType, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
618Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6)
619{
620    return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4, A5, A6)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4, a5, a6)));
621}
622
623typedef Function<void()> Closure;
624
625}
626
627using WTF::Function;
628using WTF::bind;
629using WTF::Closure;
630
631#endif // WTF_Functional_h
632