Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 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, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #ifndef WTF_Functional_h | 26 #ifndef WTF_Functional_h |
| 27 #define WTF_Functional_h | 27 #define WTF_Functional_h |
| 28 | 28 |
| 29 #include "base/tuple.h" | |
| 29 #include "wtf/Allocator.h" | 30 #include "wtf/Allocator.h" |
| 30 #include "wtf/Assertions.h" | 31 #include "wtf/Assertions.h" |
| 31 #include "wtf/PassOwnPtr.h" | 32 #include "wtf/PassOwnPtr.h" |
| 32 #include "wtf/PassRefPtr.h" | 33 #include "wtf/PassRefPtr.h" |
| 33 #include "wtf/RefPtr.h" | 34 #include "wtf/RefPtr.h" |
| 34 #include "wtf/ThreadSafeRefCounted.h" | 35 #include "wtf/ThreadSafeRefCounted.h" |
| 35 #include "wtf/WeakPtr.h" | 36 #include "wtf/WeakPtr.h" |
| 37 #include <tuple> | |
|
Nico
2016/02/09 03:16:53
It's a bit unfortunate that this includes both bas
Yuta Kitamura
2016/02/09 05:47:43
The only reason I added base/tuple.h was base::Ind
| |
| 36 | 38 |
| 37 namespace WTF { | 39 namespace WTF { |
| 38 | 40 |
| 39 // Functional.h provides a very simple way to bind a function pointer and argume nts together into a function object | 41 // Functional.h provides a very simple way to bind a function pointer and argume nts together into a function object |
| 40 // that can be stored, copied and invoked, similar to how boost::bind and std::b ind in C++11. | 42 // that can be stored, copied and invoked, similar to how boost::bind and std::b ind in C++11. |
| 41 | 43 |
| 42 // Use threadSafeBind() or createCrossThreadTask() if the function/task is | 44 // Use threadSafeBind() or createCrossThreadTask() if the function/task is |
| 43 // called on a (potentially) different thread from the current thread. | 45 // called on a (potentially) different thread from the current thread. |
| 44 | 46 |
| 45 // A FunctionWrapper is a class template that can wrap a function pointer or a m ember function pointer and | 47 // A FunctionWrapper is a class template that can wrap a function pointer or a m ember function pointer and |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 class Function<R(Args...)> { | 142 class Function<R(Args...)> { |
| 141 USING_FAST_MALLOC(Function); | 143 USING_FAST_MALLOC(Function); |
| 142 WTF_MAKE_NONCOPYABLE(Function); | 144 WTF_MAKE_NONCOPYABLE(Function); |
| 143 public: | 145 public: |
| 144 virtual ~Function() { } | 146 virtual ~Function() { } |
| 145 virtual R operator()(Args... args) = 0; | 147 virtual R operator()(Args... args) = 0; |
| 146 protected: | 148 protected: |
| 147 Function() = default; | 149 Function() = default; |
| 148 }; | 150 }; |
| 149 | 151 |
| 150 template<int boundArgsCount, typename FunctionWrapper, typename FunctionType> | 152 template <typename BoundParametersTuple, typename FunctionWrapper, typename... U nboundParameters> |
| 151 class PartBoundFunctionImpl; | 153 class PartBoundFunctionImpl; |
| 152 | 154 |
| 153 // Specialization for unbound functions. | 155 template <typename... BoundParameters, typename FunctionWrapper, typename... Unb oundParameters> |
| 154 template<typename FunctionWrapper, typename R, typename... UnboundParams> | 156 class PartBoundFunctionImpl<std::tuple<BoundParameters...>, FunctionWrapper, Unb oundParameters...> final : public Function<typename FunctionWrapper::ResultType( UnboundParameters...)> { |
| 155 class PartBoundFunctionImpl<0, FunctionWrapper, R(UnboundParams...)> final : pub lic Function<typename FunctionWrapper::ResultType(UnboundParams...)> { | |
| 156 public: | 157 public: |
| 157 PartBoundFunctionImpl(FunctionWrapper functionWrapper) | 158 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, const BoundP arameters&... bound) |
| 158 : m_functionWrapper(functionWrapper) | 159 : m_functionWrapper(functionWrapper) |
| 160 , m_bound(ParamStorageTraits<BoundParameters>::wrap(bound)...) | |
| 159 { | 161 { |
| 160 } | 162 } |
| 161 | 163 |
| 162 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | 164 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound ) override |
| 163 { | 165 { |
| 164 return m_functionWrapper(params...); | 166 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to |
| 167 // pass a list of indices to a worker function template. | |
| 168 return callInternal(unbound..., base::MakeIndexSequence<sizeof...(BoundP arameters)>()); | |
| 165 } | 169 } |
| 166 | 170 |
| 167 private: | 171 private: |
| 168 FunctionWrapper m_functionWrapper; | 172 template <std::size_t... boundIndices> |
| 169 }; | 173 typename FunctionWrapper::ResultType callInternal(UnboundParameters... unbou nd, const base::IndexSequence<boundIndices...>&) |
| 170 | |
| 171 template<typename FunctionWrapper, typename R, typename P1, typename... UnboundP arams> | |
| 172 class PartBoundFunctionImpl<1, FunctionWrapper, R(P1, UnboundParams...)> final : public Function<typename FunctionWrapper::ResultType(UnboundParams...)> { | |
| 173 public: | |
| 174 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1) | |
| 175 : m_functionWrapper(functionWrapper) | |
| 176 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 177 { | 174 { |
| 175 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. | |
| 176 return m_functionWrapper(ParamStorageTraits<BoundParameters>::unwrap(std ::get<boundIndices>(m_bound))..., unbound...); | |
| 178 } | 177 } |
| 179 | 178 |
| 180 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 181 { | |
| 182 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), params... ); | |
| 183 } | |
| 184 | |
| 185 private: | |
| 186 FunctionWrapper m_functionWrapper; | 179 FunctionWrapper m_functionWrapper; |
| 187 typename ParamStorageTraits<P1>::StorageType m_p1; | 180 std::tuple<typename ParamStorageTraits<BoundParameters>::StorageType...> m_b ound; |
| 188 }; | |
| 189 | |
| 190 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e... UnboundParams> | |
| 191 class PartBoundFunctionImpl<2, FunctionWrapper, R(P1, P2, UnboundParams...)> fin al : public Function<typename FunctionWrapper::ResultType(UnboundParams...)> { | |
| 192 public: | |
| 193 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2) | |
| 194 : m_functionWrapper(functionWrapper) | |
| 195 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 196 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 197 { | |
| 198 } | |
| 199 | |
| 200 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 201 { | |
| 202 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), params...); | |
| 203 } | |
| 204 | |
| 205 private: | |
| 206 FunctionWrapper m_functionWrapper; | |
| 207 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 208 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 209 }; | |
| 210 | |
| 211 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e P3, typename... UnboundParams> | |
| 212 class PartBoundFunctionImpl<3, FunctionWrapper, R(P1, P2, P3, UnboundParams...)> final : public Function<typename FunctionWrapper::ResultType(UnboundParams...)> { | |
| 213 public: | |
| 214 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2, const P3& p3) | |
| 215 : m_functionWrapper(functionWrapper) | |
| 216 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 217 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 218 , m_p3(ParamStorageTraits<P3>::wrap(p3)) | |
| 219 { | |
| 220 } | |
| 221 | |
| 222 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 223 { | |
| 224 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), params...); | |
| 225 } | |
| 226 | |
| 227 private: | |
| 228 FunctionWrapper m_functionWrapper; | |
| 229 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 230 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 231 typename ParamStorageTraits<P3>::StorageType m_p3; | |
| 232 }; | |
| 233 | |
| 234 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e P3, typename P4, typename... UnboundParams> | |
| 235 class PartBoundFunctionImpl<4, FunctionWrapper, R(P1, P2, P3, P4, UnboundParams. ..)> final : public Function<typename FunctionWrapper::ResultType(UnboundParams. ..)> { | |
| 236 public: | |
| 237 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2, const P3& p3, const P4& p4) | |
| 238 : m_functionWrapper(functionWrapper) | |
| 239 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 240 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 241 , m_p3(ParamStorageTraits<P3>::wrap(p3)) | |
| 242 , m_p4(ParamStorageTraits<P4>::wrap(p4)) | |
| 243 { | |
| 244 } | |
| 245 | |
| 246 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 247 { | |
| 248 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageT raits<P4>::unwrap(m_p4), params...); | |
| 249 } | |
| 250 | |
| 251 private: | |
| 252 FunctionWrapper m_functionWrapper; | |
| 253 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 254 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 255 typename ParamStorageTraits<P3>::StorageType m_p3; | |
| 256 typename ParamStorageTraits<P4>::StorageType m_p4; | |
| 257 }; | |
| 258 | |
| 259 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e P3, typename P4, typename P5, typename... UnboundParams> | |
| 260 class PartBoundFunctionImpl<5, FunctionWrapper, R(P1, P2, P3, P4, P5, UnboundPar ams...)> final : public Function<typename FunctionWrapper::ResultType(UnboundPar ams...)> { | |
| 261 public: | |
| 262 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2, const P3& p3, const P4& p4, const P5& p5) | |
| 263 : m_functionWrapper(functionWrapper) | |
| 264 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 265 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 266 , m_p3(ParamStorageTraits<P3>::wrap(p3)) | |
| 267 , m_p4(ParamStorageTraits<P4>::wrap(p4)) | |
| 268 , m_p5(ParamStorageTraits<P5>::wrap(p5)) | |
| 269 { | |
| 270 } | |
| 271 | |
| 272 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 273 { | |
| 274 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageT raits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5), params...); | |
| 275 } | |
| 276 | |
| 277 private: | |
| 278 FunctionWrapper m_functionWrapper; | |
| 279 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 280 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 281 typename ParamStorageTraits<P3>::StorageType m_p3; | |
| 282 typename ParamStorageTraits<P4>::StorageType m_p4; | |
| 283 typename ParamStorageTraits<P5>::StorageType m_p5; | |
| 284 }; | |
| 285 | |
| 286 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e P3, typename P4, typename P5, typename P6, typename... UnboundParams> | |
| 287 class PartBoundFunctionImpl<6, FunctionWrapper, R(P1, P2, P3, P4, P5, P6, Unboun dParams...)> final : public Function<typename FunctionWrapper::ResultType(Unboun dParams...)> { | |
| 288 public: | |
| 289 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) | |
| 290 : m_functionWrapper(functionWrapper) | |
| 291 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 292 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 293 , m_p3(ParamStorageTraits<P3>::wrap(p3)) | |
| 294 , m_p4(ParamStorageTraits<P4>::wrap(p4)) | |
| 295 , m_p5(ParamStorageTraits<P5>::wrap(p5)) | |
| 296 , m_p6(ParamStorageTraits<P6>::wrap(p6)) | |
| 297 { | |
| 298 } | |
| 299 | |
| 300 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 301 { | |
| 302 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageT raits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5), ParamStorageTrait s<P6>::unwrap(m_p6), params...); | |
| 303 } | |
| 304 | |
| 305 private: | |
| 306 FunctionWrapper m_functionWrapper; | |
| 307 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 308 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 309 typename ParamStorageTraits<P3>::StorageType m_p3; | |
| 310 typename ParamStorageTraits<P4>::StorageType m_p4; | |
| 311 typename ParamStorageTraits<P5>::StorageType m_p5; | |
| 312 typename ParamStorageTraits<P6>::StorageType m_p6; | |
| 313 }; | |
| 314 | |
| 315 template<typename FunctionWrapper, typename R, typename P1, typename P2, typenam e P3, typename P4, typename P5, typename P6, typename P7, typename... UnboundPar ams> | |
| 316 class PartBoundFunctionImpl<7, FunctionWrapper, R(P1, P2, P3, P4, P5, P6, P7, Un boundParams...)> final : public Function<typename FunctionWrapper::ResultType(Un boundParams...)> { | |
| 317 public: | |
| 318 PartBoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P 2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7) | |
| 319 : m_functionWrapper(functionWrapper) | |
| 320 , m_p1(ParamStorageTraits<P1>::wrap(p1)) | |
| 321 , m_p2(ParamStorageTraits<P2>::wrap(p2)) | |
| 322 , m_p3(ParamStorageTraits<P3>::wrap(p3)) | |
| 323 , m_p4(ParamStorageTraits<P4>::wrap(p4)) | |
| 324 , m_p5(ParamStorageTraits<P5>::wrap(p5)) | |
| 325 , m_p6(ParamStorageTraits<P6>::wrap(p6)) | |
| 326 , m_p7(ParamStorageTraits<P7>::wrap(p7)) | |
| 327 { | |
| 328 } | |
| 329 | |
| 330 typename FunctionWrapper::ResultType operator()(UnboundParams... params) ove rride | |
| 331 { | |
| 332 return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStor ageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageT raits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5), ParamStorageTrait s<P6>::unwrap(m_p6), ParamStorageTraits<P7>::unwrap(m_p7), params...); | |
| 333 } | |
| 334 | |
| 335 private: | |
| 336 FunctionWrapper m_functionWrapper; | |
| 337 typename ParamStorageTraits<P1>::StorageType m_p1; | |
| 338 typename ParamStorageTraits<P2>::StorageType m_p2; | |
| 339 typename ParamStorageTraits<P3>::StorageType m_p3; | |
| 340 typename ParamStorageTraits<P4>::StorageType m_p4; | |
| 341 typename ParamStorageTraits<P5>::StorageType m_p5; | |
| 342 typename ParamStorageTraits<P6>::StorageType m_p6; | |
| 343 typename ParamStorageTraits<P7>::StorageType m_p7; | |
| 344 }; | 181 }; |
| 345 | 182 |
| 346 | 183 |
| 347 template<typename... UnboundArgs, typename FunctionType, typename... BoundArgs> | 184 template<typename... UnboundParameters, typename FunctionType, typename... Bound Parameters> |
| 348 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundAr gs...)>> bind(FunctionType function, const BoundArgs&... boundArgs) | 185 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa rameters...)>> bind(FunctionType function, const BoundParameters&... boundParame ters) |
| 349 { | 186 { |
| 350 const int boundArgsCount = sizeof...(BoundArgs); | 187 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound |
| 351 using BoundFunctionType = PartBoundFunctionImpl<boundArgsCount, FunctionWrap per<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType(BoundArgs. .., UnboundArgs...)>; | 188 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th is type isn't actually created; |
| 352 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function ), boundArgs...)); | 189 // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter |
| 190 // pack can be used instead of std::tuple. std::tuple is used just because i t's most convenient for this purpose. | |
| 191 using BoundFunctionType = PartBoundFunctionImpl<std::tuple<BoundParameters.. .>, FunctionWrapper<FunctionType>, UnboundParameters...>; | |
| 192 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function ), boundParameters...)); | |
| 353 } | 193 } |
| 354 | 194 |
| 355 typedef Function<void()> Closure; | 195 typedef Function<void()> Closure; |
| 356 | 196 |
| 357 } // namespace WTF | 197 } // namespace WTF |
| 358 | 198 |
| 359 using WTF::Function; | 199 using WTF::Function; |
| 360 using WTF::bind; | 200 using WTF::bind; |
| 361 using WTF::Closure; | 201 using WTF::Closure; |
| 362 | 202 |
| 363 #endif // WTF_Functional_h | 203 #endif // WTF_Functional_h |
| OLD | NEW |