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 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { ret urn value.get(); } | 169 static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { ret urn value.get(); } |
| 170 }; | 170 }; |
| 171 | 171 |
| 172 template<> struct ParamStorageTraits<void*> { | 172 template<> struct ParamStorageTraits<void*> { |
| 173 typedef void* StorageType; | 173 typedef void* StorageType; |
| 174 | 174 |
| 175 static StorageType wrap(void* value) { return value; } | 175 static StorageType wrap(void* value) { return value; } |
| 176 static void* unwrap(const StorageType& value) { return value; } | 176 static void* unwrap(const StorageType& value) { return value; } |
| 177 }; | 177 }; |
| 178 | 178 |
| 179 template<typename> | 179 enum FunctionThreadAffinity { |
| 180 CrossThreadAffinity, | |
| 181 SameThreadAffinity | |
| 182 }; | |
| 183 | |
| 184 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> | |
| 180 class Function; | 185 class Function; |
| 181 | 186 |
| 182 template<typename R, typename... Args> | 187 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> |
| 183 class Function<R(Args...)> { | 188 class Function<R(Args...), threadAffinity> { |
| 184 USING_FAST_MALLOC(Function); | 189 USING_FAST_MALLOC(Function); |
| 185 WTF_MAKE_NONCOPYABLE(Function); | 190 WTF_MAKE_NONCOPYABLE(Function); |
| 186 public: | 191 public: |
| 187 virtual ~Function() { } | 192 virtual ~Function() { } |
| 188 virtual R operator()(Args... args) = 0; | 193 virtual R operator()(Args... args) = 0; |
| 189 protected: | 194 protected: |
| 190 Function() = default; | 195 Function() = default; |
| 196 void checkThread() { } | |
| 191 }; | 197 }; |
| 192 | 198 |
| 193 template <typename BoundParametersTuple, typename FunctionWrapper, typename... U nboundParameters> | 199 #if ENABLE(ASSERT) |
| 200 template<typename R, typename... Args> | |
| 201 class Function<R(Args...), SameThreadAffinity> { | |
| 202 USING_FAST_MALLOC(Function); | |
| 203 WTF_MAKE_NONCOPYABLE(Function); | |
| 204 public: | |
| 205 virtual ~Function() | |
| 206 { | |
| 207 checkThread(); | |
| 208 } | |
| 209 virtual R operator()(Args... args) = 0; | |
| 210 protected: | |
| 211 Function() | |
| 212 : m_createdThread(currentThread()) | |
| 213 { | |
| 214 } | |
| 215 | |
| 216 void NEVER_INLINE checkThread() | |
|
kinuko
2016/03/02 07:30:56
sorry, why we need this to be noinline?
hiroshige
2016/03/03 02:21:07
This is to make checkThread() to appear in the cra
| |
| 217 { | |
| 218 RELEASE_ASSERT(m_createdThread == currentThread()); | |
| 219 } | |
| 220 | |
| 221 private: | |
| 222 ThreadIdentifier m_createdThread; | |
| 223 }; | |
| 224 #endif | |
| 225 | |
| 226 template <FunctionThreadAffinity threadAffinity, typename BoundParametersTuple, typename FunctionWrapper, typename... UnboundParameters> | |
| 194 class PartBoundFunctionImpl; | 227 class PartBoundFunctionImpl; |
| 195 | 228 |
| 196 template <typename... BoundParameters, typename FunctionWrapper, typename... Unb oundParameters> | 229 template <FunctionThreadAffinity threadAffinity, typename... BoundParameters, ty pename FunctionWrapper, typename... UnboundParameters> |
| 197 class PartBoundFunctionImpl<std::tuple<BoundParameters...>, FunctionWrapper, Unb oundParameters...> final : public Function<typename FunctionWrapper::ResultType( UnboundParameters...)> { | 230 class PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters...>, Func tionWrapper, UnboundParameters...> final : public Function<typename FunctionWrap per::ResultType(UnboundParameters...), threadAffinity> { |
| 198 public: | 231 public: |
| 199 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain | 232 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain |
| 200 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. | 233 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. |
| 201 // So, sadly, we have write down the full type signature in all places where storage traits are needed. | 234 // So, sadly, we have write down the full type signature in all places where storage traits are needed. |
| 202 // | 235 // |
| 203 // template <typename T> | 236 // template <typename T> |
| 204 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; | 237 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; |
| 205 | 238 |
| 206 // Note that BoundParameters can be const T&, T&& or a mix of these. | 239 // Note that BoundParameters can be const T&, T&& or a mix of these. |
| 207 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) | 240 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) |
| 208 : m_functionWrapper(functionWrapper) | 241 : m_functionWrapper(functionWrapper) |
| 209 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type> ::wrap(std::forward<BoundParameters>(bound))...) | 242 , m_bound(ParamStorageTraits<typename std::decay<BoundParameters>::type> ::wrap(std::forward<BoundParameters>(bound))...) |
| 210 { | 243 { |
| 211 } | 244 } |
| 212 | 245 |
| 213 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound ) override | 246 typename FunctionWrapper::ResultType operator()(UnboundParameters... unbound ) override |
| 214 { | 247 { |
| 215 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to | 248 // 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. | 249 // pass a list of indices to a worker function template. |
| 217 return callInternal(unbound..., base::MakeIndexSequence<sizeof...(BoundP arameters)>()); | 250 return callInternal(unbound..., base::MakeIndexSequence<sizeof...(BoundP arameters)>()); |
| 218 } | 251 } |
| 219 | 252 |
| 220 private: | 253 private: |
| 221 template <std::size_t... boundIndices> | 254 template <std::size_t... boundIndices> |
| 222 typename FunctionWrapper::ResultType callInternal(UnboundParameters... unbou nd, const base::IndexSequence<boundIndices...>&) | 255 typename FunctionWrapper::ResultType callInternal(UnboundParameters... unbou nd, const base::IndexSequence<boundIndices...>&) |
| 223 { | 256 { |
| 257 this->checkThread(); | |
| 224 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. | 258 // 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...); | 259 return m_functionWrapper(ParamStorageTraits<typename std::decay<BoundPar ameters>::type>::unwrap(std::get<boundIndices>(m_bound))..., unbound...); |
| 226 } | 260 } |
| 227 | 261 |
| 228 FunctionWrapper m_functionWrapper; | 262 FunctionWrapper m_functionWrapper; |
| 229 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; | 263 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; |
| 230 }; | 264 }; |
| 231 | 265 |
| 232 template <typename... UnboundParameters, typename FunctionType, typename... Boun dParameters> | 266 template <FunctionThreadAffinity threadAffinity, typename... UnboundParameters, typename FunctionType, typename... BoundParameters> |
| 233 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa rameters...)>> bind(FunctionType function, BoundParameters&&... boundParameters) | 267 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa rameters...), threadAffinity>> bindInternal(FunctionType function, BoundParamete rs&&... boundParameters) |
| 234 { | 268 { |
| 235 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound | 269 // 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; | 270 // 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 | 271 // 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. | 272 // 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...>; | 273 using BoundFunctionType = PartBoundFunctionImpl<threadAffinity, std::tuple<B oundParameters&&...>, FunctionWrapper<FunctionType>, UnboundParameters...>; |
| 240 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function ), std::forward<BoundParameters>(boundParameters)...)); | 274 return adoptPtr(new BoundFunctionType(FunctionWrapper<FunctionType>(function ), std::forward<BoundParameters>(boundParameters)...)); |
| 241 } | 275 } |
| 242 | 276 |
| 243 typedef Function<void()> Closure; | 277 template <typename... UnboundParameters, typename FunctionType, typename... Boun dParameters> |
| 278 PassOwnPtr<Function<typename FunctionWrapper<FunctionType>::ResultType(UnboundPa rameters...), SameThreadAffinity>> bind(FunctionType function, BoundParameters&& ... boundParameters) | |
| 279 { | |
| 280 return bindInternal<SameThreadAffinity, UnboundParameters...>(function, std: :forward<BoundParameters>(boundParameters)...); | |
| 281 } | |
| 282 | |
| 283 typedef Function<void(), SameThreadAffinity> Closure; | |
| 284 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; | |
| 244 | 285 |
| 245 } // namespace WTF | 286 } // namespace WTF |
| 246 | 287 |
| 247 using WTF::Function; | 288 using WTF::Function; |
| 248 using WTF::bind; | 289 using WTF::bind; |
| 249 using WTF::Closure; | 290 using WTF::Closure; |
| 291 using WTF::CrossThreadClosure; | |
| 250 | 292 |
| 251 #endif // WTF_Functional_h | 293 #endif // WTF_Functional_h |
| OLD | NEW |