| 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 23 matching lines...) Expand all Loading... |
| 34 #include "wtf/RefPtr.h" | 34 #include "wtf/RefPtr.h" |
| 35 #include "wtf/ThreadSafeRefCounted.h" | 35 #include "wtf/ThreadSafeRefCounted.h" |
| 36 #include "wtf/WeakPtr.h" | 36 #include "wtf/WeakPtr.h" |
| 37 #include <tuple> | 37 #include <tuple> |
| 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 |
| 45 // Thread Safety: |
| 44 // | 46 // |
| 45 // Use threadSafeBind() or createCrossThreadTask() if the function/task is | 47 // WTF::bind() and SameThreadClosure should be used for same-thread closures |
| 46 // called on a (potentially) different thread from the current thread. | 48 // only, i.e. the closures must be created, executed and destructed on |
| 49 // the same thread. |
| 50 // Use threadSafeBind() and CrossThreadClosure if the function/task is called |
| 51 // or destructed on a (potentially) different thread from the current thread. |
| 47 | 52 |
| 48 // WTF::bind() and move semantics | 53 // WTF::bind() and move semantics |
| 49 // ============================== | 54 // ============================== |
| 50 // | 55 // |
| 51 // For unbound parameters (arguments supplied later on the bound functor directl
y), there are two ways to pass movable | 56 // For unbound parameters (arguments supplied later on the bound functor directl
y), there are two ways to pass movable |
| 52 // arguments: | 57 // arguments: |
| 53 // | 58 // |
| 54 // 1) Pass by rvalue reference. | 59 // 1) Pass by rvalue reference. |
| 55 // | 60 // |
| 56 // void yourFunction(Argument&& argument) { ... } | 61 // void yourFunction(Argument&& argument) { ... } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { ret
urn value.get(); } | 189 static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { ret
urn value.get(); } |
| 185 }; | 190 }; |
| 186 | 191 |
| 187 template<> struct ParamStorageTraits<void*> { | 192 template<> struct ParamStorageTraits<void*> { |
| 188 typedef void* StorageType; | 193 typedef void* StorageType; |
| 189 | 194 |
| 190 static StorageType wrap(void* value) { return value; } | 195 static StorageType wrap(void* value) { return value; } |
| 191 static void* unwrap(const StorageType& value) { return value; } | 196 static void* unwrap(const StorageType& value) { return value; } |
| 192 }; | 197 }; |
| 193 | 198 |
| 194 template<typename> | 199 enum FunctionThreadAffinity { |
| 200 CrossThreadAffinity, |
| 201 SameThreadAffinity |
| 202 }; |
| 203 |
| 204 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> |
| 195 class Function; | 205 class Function; |
| 196 | 206 |
| 197 template<typename R, typename... Args> | 207 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> |
| 198 class Function<R(Args...)> { | 208 class Function<R(Args...), threadAffinity> { |
| 199 USING_FAST_MALLOC(Function); | 209 USING_FAST_MALLOC(Function); |
| 200 WTF_MAKE_NONCOPYABLE(Function); | 210 WTF_MAKE_NONCOPYABLE(Function); |
| 201 public: | 211 public: |
| 202 virtual ~Function() { } | 212 virtual ~Function() { } |
| 203 virtual R operator()(Args... args) = 0; | 213 virtual R operator()(Args... args) = 0; |
| 204 protected: | 214 protected: |
| 205 Function() = default; | 215 Function() = default; |
| 216 void checkThread() { } |
| 206 }; | 217 }; |
| 207 | 218 |
| 208 template <typename BoundParametersTuple, typename FunctionWrapper, typename... U
nboundParameters> | 219 #if ENABLE(ASSERT) |
| 220 template<typename R, typename... Args> |
| 221 class Function<R(Args...), SameThreadAffinity> { |
| 222 USING_FAST_MALLOC(Function); |
| 223 WTF_MAKE_NONCOPYABLE(Function); |
| 224 public: |
| 225 virtual ~Function() |
| 226 { |
| 227 checkThread(); |
| 228 } |
| 229 virtual R operator()(Args... args) = 0; |
| 230 protected: |
| 231 Function() |
| 232 : m_createdThread(currentThread()) |
| 233 { |
| 234 } |
| 235 |
| 236 void NEVER_INLINE checkThread() |
| 237 { |
| 238 // Function with SameThreadAffinity, including SameThreadClosure |
| 239 // created by WTF::bind() or blink::createSameThreadTask(), |
| 240 // must be called and destructed on the thread where it is created. |
| 241 // If it is intended to be used cross-thread, use |
| 242 // blink::threadSafeBind() or blink::createCrossThreadTask() instead. |
| 243 RELEASE_ASSERT(m_createdThread == currentThread()); |
| 244 } |
| 245 |
| 246 private: |
| 247 const ThreadIdentifier m_createdThread; |
| 248 }; |
| 249 #endif |
| 250 |
| 251 template <FunctionThreadAffinity threadAffinity, typename BoundParametersTuple,
typename FunctionWrapper, typename... UnboundParameters> |
| 209 class PartBoundFunctionImpl; | 252 class PartBoundFunctionImpl; |
| 210 | 253 |
| 211 template <typename... BoundParameters, typename FunctionWrapper, typename... Unb
oundParameters> | 254 template <FunctionThreadAffinity threadAffinity, typename... BoundParameters, ty
pename FunctionWrapper, typename... UnboundParameters> |
| 212 class PartBoundFunctionImpl<std::tuple<BoundParameters...>, FunctionWrapper, Unb
oundParameters...> final : public Function<typename FunctionWrapper::ResultType(
UnboundParameters...)> { | 255 class PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters...>, Func
tionWrapper, UnboundParameters...> final : public Function<typename FunctionWrap
per::ResultType(UnboundParameters...), threadAffinity> { |
| 213 public: | 256 public: |
| 214 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai
ts defined as below in order to obtain | 257 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai
ts defined as below in order to obtain |
| 215 // storage traits of UnboundParameters, but unfortunately MSVC can't handle
template using declarations correctly. | 258 // storage traits of UnboundParameters, but unfortunately MSVC can't handle
template using declarations correctly. |
| 216 // So, sadly, we have write down the full type signature in all places where
storage traits are needed. | 259 // So, sadly, we have write down the full type signature in all places where
storage traits are needed. |
| 217 // | 260 // |
| 218 // template <typename T> | 261 // template <typename T> |
| 219 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; | 262 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; |
| 220 | 263 |
| 221 // Note that BoundParameters can be const T&, T&& or a mix of these. | 264 // Note that BoundParameters can be const T&, T&& or a mix of these. |
| 222 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet
ers... bound) | 265 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet
ers... bound) |
| 223 : m_functionWrapper(functionWrapper) | 266 : m_functionWrapper(functionWrapper) |
| 224 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type>
::wrap(std::forward<BoundParameters>(bound))...) | 267 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type>
::wrap(std::forward<BoundParameters>(bound))...) |
| 225 { | 268 { |
| 226 } | 269 } |
| 227 | 270 |
| 228 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound
) override | 271 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound
) override |
| 229 { | 272 { |
| 230 // What we really want to do is to call m_functionWrapper(m_bound..., un
bound...), but to do that we need to | 273 // What we really want to do is to call m_functionWrapper(m_bound..., un
bound...), but to do that we need to |
| 231 // pass a list of indices to a worker function template. | 274 // pass a list of indices to a worker function template. |
| 232 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>(
), std::forward<UnboundParameters>(unbound)...); | 275 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>(
), std::forward<UnboundParameters>(unbound)...); |
| 233 } | 276 } |
| 234 | 277 |
| 235 private: | 278 private: |
| 236 template <std::size_t... boundIndices, typename... IncomingUnboundParameters
> | 279 template <std::size_t... boundIndices, typename... IncomingUnboundParameters
> |
| 237 typename FunctionWrapper::ResultType callInternal(const base::IndexSeque
nce<boundIndices...>&, IncomingUnboundParameters&&... unbound) | 280 typename FunctionWrapper::ResultType callInternal(const base::IndexSeque
nce<boundIndices...>&, IncomingUnboundParameters&&... unbound) |
| 238 { | 281 { |
| 282 this->checkThread(); |
| 239 // Get each element in m_bound, unwrap them, and call the function with
the desired arguments. | 283 // Get each element in m_bound, unwrap them, and call the function with
the desired arguments. |
| 240 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar
ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., std::forward<Incomi
ngUnboundParameters>(unbound)...); | 284 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar
ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., std::forward<Incomi
ngUnboundParameters>(unbound)...); |
| 241 } | 285 } |
| 242 | 286 |
| 243 FunctionWrapper m_functionWrapper; | 287 FunctionWrapper m_functionWrapper; |
| 244 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>:
:type>::StorageType...> m_bound; | 288 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>:
:type>::StorageType...> m_bound; |
| 245 }; | 289 }; |
| 246 | 290 |
| 247 template <typename... UnboundParameters, typename FunctionType, typename... Boun
dParameters> | 291 template <FunctionThreadAffinity threadAffinity, typename... UnboundParameters,
typename FunctionType, typename... BoundParameters> |
| 248 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa
rameters...)>> bind(FunctionType function, BoundParameters&&... boundParameters) | 292 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa
rameters...), threadAffinity>> bindInternal(FunctionType function, BoundParamete
rs&&... boundParameters) |
| 249 { | 293 { |
| 250 // Bound parameters' types are wrapped with std::tuple so we can pass two te
mplate parameter packs (bound | 294 // Bound parameters' types are wrapped with std::tuple so we can pass two te
mplate parameter packs (bound |
| 251 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th
is type isn't actually created; | 295 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th
is type isn't actually created; |
| 252 // std::tuple<> is just for carrying the bound parameters' types. Any other
class template taking a type parameter | 296 // std::tuple<> is just for carrying the bound parameters' types. Any other
class template taking a type parameter |
| 253 // pack can be used instead of std::tuple. std::tuple is used just because i
t's most convenient for this purpose. | 297 // pack can be used instead of std::tuple. std::tuple is used just because i
t's most convenient for this purpose. |
| 254 using BoundFunctionType = PartBoundFunctionImpl<std::tuple<BoundParameters&&
...>, FunctionWrapper<FunctionType>, UnboundParameters...>; | 298 using BoundFunctionType = PartBoundFunctionImpl<threadAffinity, std::tuple<B
oundParameters&&...>, FunctionWrapper<FunctionType>, UnboundParameters...>; |
| 255 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function
), std::forward<BoundParameters>(boundParameters)...)); | 299 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function
), std::forward<BoundParameters>(boundParameters)...)); |
| 256 } | 300 } |
| 257 | 301 |
| 258 typedef Function<void()> Closure; | 302 template <typename... UnboundParameters, typename FunctionType, typename... Boun
dParameters> |
| 303 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa
rameters...), SameThreadAffinity>> bind(FunctionType function, BoundParameters&&
... boundParameters) |
| 304 { |
| 305 return bindInternal<SameThreadAffinity, UnboundParameters...>(function, std:
:forward<BoundParameters>(boundParameters)...); |
| 306 } |
| 307 |
| 308 typedef Function<void(), SameThreadAffinity> SameThreadClosure; |
| 309 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; |
| 259 | 310 |
| 260 } // namespace WTF | 311 } // namespace WTF |
| 261 | 312 |
| 262 using WTF::Function; | 313 using WTF::Function; |
| 263 using WTF::bind; | 314 using WTF::bind; |
| 264 using WTF::Closure; | 315 using WTF::SameThreadClosure; |
| 316 using WTF::CrossThreadClosure; |
| 265 | 317 |
| 266 #endif // WTF_Functional_h | 318 #endif // WTF_Functional_h |
| OLD | NEW |