| 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 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 #include <utility> | 38 #include <utility> |
| 39 | 39 |
| 40 namespace WTF { | 40 namespace WTF { |
| 41 | 41 |
| 42 // Functional.h provides a very simple way to bind a function pointer and argume
nts together into a function object | 42 // Functional.h provides a very simple way to bind a function pointer and argume
nts together into a function object |
| 43 // that can be stored, copied and invoked, similar to how boost::bind and std::b
ind in C++11. | 43 // that can be stored, copied and invoked, similar to how boost::bind and std::b
ind in C++11. |
| 44 // | 44 // |
| 45 // Use threadSafeBind() or createCrossThreadTask() if the function/task is | 45 // Use threadSafeBind() or createCrossThreadTask() if the function/task is |
| 46 // called on a (potentially) different thread from the current thread. | 46 // called on a (potentially) different thread from the current thread. |
| 47 | 47 |
| 48 // Bind and rvalue references: | 48 // WTF::bind() and move semantics |
| 49 // ============================== |
| 49 // | 50 // |
| 50 // For unbound parameters (arguments supplied later on the bound functor), we do
n't support moving-in and moving-out | 51 // For unbound parameters (arguments supplied later on the bound functor directl
y), there are two ways to pass movable |
| 51 // at this moment, but we are willing to support that soon. | 52 // arguments: |
| 53 // |
| 54 // 1) Pass by rvalue reference. |
| 55 // |
| 56 // void yourFunction(Argument&& argument) { ... } |
| 57 // OwnPtr<Function<void(Argument&&)>> functor = bind<Argument&&>(your
Function); |
| 58 // |
| 59 // 2) Pass by value. |
| 60 // |
| 61 // void yourFunction(Argument argument) { ... } |
| 62 // OwnPtr<Function<void(Argument)>> functor = bind<Argument>(yourFunc
tion); |
| 63 // |
| 64 // Note that with the latter there will be *two* move constructions happening, b
ecause there needs to be at least one |
| 65 // intermediary function call taking an argument of type "Argument" (i.e. passed
by value). The former case does not |
| 66 // require any move constructions inbetween. |
| 52 // | 67 // |
| 53 // For bound parameters (arguments supplied on the creation of a functor), you c
an move your argument into the internal | 68 // For bound parameters (arguments supplied on the creation of a functor), you c
an move your argument into the internal |
| 54 // storage of the functor by supplying an rvalue to that argument (this is done
in wrap() of ParamStorageTraits). | 69 // storage of the functor by supplying an rvalue to that argument (this is done
in wrap() of ParamStorageTraits). |
| 55 // However, to make the functor be able to get called multiple times, the stored
object does not get moved out | 70 // However, to make the functor be able to get called multiple times, the stored
object does not get moved out |
| 56 // automatically when the underlying function is actually invoked. If you want t
o move the argument throughout the | 71 // automatically when the underlying function is actually invoked. If you want t
o move the argument throughout the |
| 57 // process, you can do so by receiving the argument as a non-const lvalue refere
nce and applying std::move() to it: | 72 // process, you can do so by receiving the argument as a non-const lvalue refere
nce and applying std::move() to it: |
| 58 // | 73 // |
| 59 // void yourFunction(Argument& argument) | 74 // void yourFunction(Argument& argument) |
| 60 // { | 75 // { |
| 61 // std::move(argument); // Move out the argument from the internal stora
ge. | 76 // std::move(argument); // Move out the argument from the internal stora
ge. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet
ers... bound) | 222 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet
ers... bound) |
| 208 : m_functionWrapper(functionWrapper) | 223 : m_functionWrapper(functionWrapper) |
| 209 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type>
::wrap(std::forward<BoundParameters>(bound))...) | 224 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type>
::wrap(std::forward<BoundParameters>(bound))...) |
| 210 { | 225 { |
| 211 } | 226 } |
| 212 | 227 |
| 213 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound
) override | 228 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound
) override |
| 214 { | 229 { |
| 215 // What we really want to do is to call m_functionWrapper(m_bound..., un
bound...), but to do that we need to | 230 // What we really want to do is to call m_functionWrapper(m_bound..., un
bound...), but to do that we need to |
| 216 // pass a list of indices to a worker function template. | 231 // pass a list of indices to a worker function template. |
| 217 return callInternal(unbound..., base::MakeIndexSequence<sizeof...(BoundP
arameters)>()); | 232 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>(
), std::forward<UnboundParameters>(unbound)...); |
| 218 } | 233 } |
| 219 | 234 |
| 220 private: | 235 private: |
| 221 template <std::size_t... boundIndices> | 236 template <std::size_t... boundIndices, typename... IncomingUnboundParameters
> |
| 222 typename FunctionWrapper::ResultType callInternal(UnboundParameters... unbou
nd, const base::IndexSequence<boundIndices...>&) | 237 typename FunctionWrapper::ResultType callInternal(const base::IndexSeque
nce<boundIndices...>&, IncomingUnboundParameters&&... unbound) |
| 223 { | 238 { |
| 224 // Get each element in m_bound, unwrap them, and call the function with
the desired arguments. | 239 // Get each element in m_bound, unwrap them, and call the function with
the desired arguments. |
| 225 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar
ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., unbound...); | 240 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar
ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., std::forward<Incomi
ngUnboundParameters>(unbound)...); |
| 226 } | 241 } |
| 227 | 242 |
| 228 FunctionWrapper m_functionWrapper; | 243 FunctionWrapper m_functionWrapper; |
| 229 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>:
:type>::StorageType...> m_bound; | 244 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>:
:type>::StorageType...> m_bound; |
| 230 }; | 245 }; |
| 231 | 246 |
| 232 template <typename... UnboundParameters, typename FunctionType, typename... Boun
dParameters> | 247 template <typename... UnboundParameters, typename FunctionType, typename... Boun
dParameters> |
| 233 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa
rameters...)>> bind(FunctionType function, BoundParameters&&... boundParameters) | 248 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa
rameters...)>> bind(FunctionType function, BoundParameters&&... boundParameters) |
| 234 { | 249 { |
| 235 // Bound parameters' types are wrapped with std::tuple so we can pass two te
mplate parameter packs (bound | 250 // Bound parameters' types are wrapped with std::tuple so we can pass two te
mplate parameter packs (bound |
| 236 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th
is type isn't actually created; | 251 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th
is type isn't actually created; |
| 237 // std::tuple<> is just for carrying the bound parameters' types. Any other
class template taking a type parameter | 252 // std::tuple<> is just for carrying the bound parameters' types. Any other
class template taking a type parameter |
| 238 // pack can be used instead of std::tuple. std::tuple is used just because i
t's most convenient for this purpose. | 253 // pack can be used instead of std::tuple. std::tuple is used just because i
t's most convenient for this purpose. |
| 239 using BoundFunctionType = PartBoundFunctionImpl<std::tuple<BoundParameters&&
...>, FunctionWrapper<FunctionType>, UnboundParameters...>; | 254 using BoundFunctionType = PartBoundFunctionImpl<std::tuple<BoundParameters&&
...>, FunctionWrapper<FunctionType>, UnboundParameters...>; |
| 240 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function
), std::forward<BoundParameters>(boundParameters)...)); | 255 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function
), std::forward<BoundParameters>(boundParameters)...)); |
| 241 } | 256 } |
| 242 | 257 |
| 243 typedef Function<void()> Closure; | 258 typedef Function<void()> Closure; |
| 244 | 259 |
| 245 } // namespace WTF | 260 } // namespace WTF |
| 246 | 261 |
| 247 using WTF::Function; | 262 using WTF::Function; |
| 248 using WTF::bind; | 263 using WTF::bind; |
| 249 using WTF::Closure; | 264 using WTF::Closure; |
| 250 | 265 |
| 251 #endif // WTF_Functional_h | 266 #endif // WTF_Functional_h |
| OLD | NEW |