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/bind.h" | 29 #include "base/bind.h" |
30 #include "base/threading/thread_checker.h" | |
30 #include "base/tuple.h" | 31 #include "base/tuple.h" |
31 #include "wtf/Allocator.h" | 32 #include "wtf/Allocator.h" |
32 #include "wtf/Assertions.h" | 33 #include "wtf/Assertions.h" |
33 #include "wtf/PassRefPtr.h" | 34 #include "wtf/PassRefPtr.h" |
34 #include "wtf/PtrUtil.h" | 35 #include "wtf/PtrUtil.h" |
35 #include "wtf/RefPtr.h" | 36 #include "wtf/RefPtr.h" |
36 #include "wtf/ThreadSafeRefCounted.h" | 37 #include "wtf/ThreadSafeRefCounted.h" |
37 #include "wtf/TypeTraits.h" | 38 #include "wtf/TypeTraits.h" |
38 #include "wtf/WeakPtr.h" | 39 #include "wtf/WeakPtr.h" |
39 #include <tuple> | 40 #include <tuple> |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 return UnretainedWrapper<T, SameThreadAffinity>(value); | 149 return UnretainedWrapper<T, SameThreadAffinity>(value); |
149 } | 150 } |
150 | 151 |
151 template <typename T> | 152 template <typename T> |
152 UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) | 153 UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) |
153 { | 154 { |
154 static_assert(!WTF::IsGarbageCollectedType<T>::value, "crossThreadUnretained () + GCed type is forbidden"); | 155 static_assert(!WTF::IsGarbageCollectedType<T>::value, "crossThreadUnretained () + GCed type is forbidden"); |
155 return UnretainedWrapper<T, CrossThreadAffinity>(value); | 156 return UnretainedWrapper<T, CrossThreadAffinity>(value); |
156 } | 157 } |
157 | 158 |
158 // A FunctionWrapper is a class template that can wrap a function pointer or a m ember function pointer and | |
159 // provide a unified interface for calling that function. | |
160 template <typename> | |
161 class FunctionWrapper; | |
162 | |
163 // Bound static functions: | |
164 template <typename R, typename... Parameters> | |
165 class FunctionWrapper<R(*)(Parameters...)> { | |
166 DISALLOW_NEW(); | |
167 public: | |
168 typedef R ResultType; | |
169 static const size_t numberOfArguments = sizeof...(Parameters); | |
170 | |
171 explicit FunctionWrapper(R(*function)(Parameters...)) | |
172 : m_function(function) | |
173 { | |
174 } | |
175 | |
176 template <typename... IncomingParameters> | |
177 R operator()(IncomingParameters&&... parameters) | |
178 { | |
179 return m_function(std::forward<IncomingParameters>(parameters)...); | |
180 } | |
181 | |
182 private: | |
183 R(*m_function)(Parameters...); | |
184 }; | |
185 | |
186 // Bound member functions: | |
187 | |
188 template <typename R, typename C, typename... Parameters> | |
189 class FunctionWrapper<R(C::*)(Parameters...)> { | |
190 DISALLOW_NEW(); | |
191 public: | |
192 typedef R ResultType; | |
193 // + 1 is for |this| as an argument. | |
194 static const size_t numberOfArguments = sizeof...(Parameters) + 1; | |
195 | |
196 explicit FunctionWrapper(R(C::*function)(Parameters...)) | |
197 : m_function(function) | |
198 { | |
199 } | |
200 | |
201 template <typename Receiver, typename... IncomingParameters> | |
202 R operator()(Receiver&& receiver, IncomingParameters&&... parameters) | |
203 { | |
204 if (base::IsWeakReceiver<typename std::decay<Receiver>::type>::value && !receiver) { | |
205 return R(); | |
206 } | |
207 | |
208 C& c = *receiver; | |
209 return (c.*m_function)(std::forward<IncomingParameters>(parameters)...); | |
210 } | |
211 | |
212 private: | |
213 R(C::*m_function)(Parameters...); | |
214 }; | |
215 | |
216 template <typename T> | 159 template <typename T> |
217 struct ParamStorageTraits { | 160 struct ParamStorageTraits { |
218 typedef T StorageType; | 161 typedef T StorageType; |
219 | 162 |
220 static_assert(!std::is_pointer<T>::value, "Raw pointers are not allowed to b ind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersistent, wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, RefPtr or unretained." ); | 163 static_assert(!std::is_pointer<T>::value, "Raw pointers are not allowed to b ind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersistent, wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, RefPtr or unretained." ); |
221 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && !IsSubclassO fTemplate<T, blink::WeakMember>::value, "Member and WeakMember are not allowed t o bind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersisten t, wrapCrossThreadPersistent or wrapCrossThreadWeakPersistent."); | 164 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && !IsSubclassO fTemplate<T, blink::WeakMember>::value, "Member and WeakMember are not allowed t o bind into WTF::Function. Wrap it with either wrapPersistent, wrapWeakPersisten t, wrapCrossThreadPersistent or wrapCrossThreadWeakPersistent."); |
222 }; | 165 }; |
223 | 166 |
224 template <typename T> | 167 template <typename T> |
225 struct ParamStorageTraits<PassRefPtr<T>> { | 168 struct ParamStorageTraits<PassRefPtr<T>> { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { | 202 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { |
260 typedef UnretainedWrapper<T, threadAffinity> StorageType; | 203 typedef UnretainedWrapper<T, threadAffinity> StorageType; |
261 }; | 204 }; |
262 | 205 |
263 template <typename T, FunctionThreadAffinity threadAffinity> | 206 template <typename T, FunctionThreadAffinity threadAffinity> |
264 T* Unwrap(const UnretainedWrapper<T, threadAffinity>& wrapped) | 207 T* Unwrap(const UnretainedWrapper<T, threadAffinity>& wrapped) |
265 { | 208 { |
266 return wrapped.value(); | 209 return wrapped.value(); |
267 } | 210 } |
268 | 211 |
269 | 212 template<typename Signature, FunctionThreadAffinity threadAffinity = SameThreadA ffinity> |
270 template<typename, FunctionThreadAffinity threadAffinity = SameThreadAffinity> | |
271 class Function; | 213 class Function; |
272 | 214 |
273 template<FunctionThreadAffinity threadAffinity, typename R, typename... Args> | 215 template<typename R, typename... Args, FunctionThreadAffinity threadAffinity> |
274 class Function<R(Args...), threadAffinity> { | 216 class Function<R(Args...), threadAffinity> { |
275 USING_FAST_MALLOC(Function); | 217 USING_FAST_MALLOC(Function); |
276 WTF_MAKE_NONCOPYABLE(Function); | 218 WTF_MAKE_NONCOPYABLE(Function); |
277 public: | 219 public: |
278 virtual ~Function() { } | 220 Function(base::Callback<R(Args...)> callback) |
279 virtual R operator()(Args... args) = 0; | 221 : m_callback(std::move(callback)) { } |
280 protected: | |
281 Function() = default; | |
282 void checkThread() { } | |
283 }; | |
284 | 222 |
285 #if ENABLE(ASSERT) | 223 ~Function() |
286 template<typename R, typename... Args> | |
287 class Function<R(Args...), SameThreadAffinity> { | |
288 USING_FAST_MALLOC(Function); | |
289 WTF_MAKE_NONCOPYABLE(Function); | |
290 public: | |
291 virtual ~Function() | |
292 { | 224 { |
293 checkThread(); | 225 DCHECK(m_threadChecker.CalledOnValidThread()); |
294 } | |
295 virtual R operator()(Args... args) = 0; | |
296 protected: | |
297 Function() | |
298 : m_createdThread(currentThread()) | |
299 { | |
300 } | 226 } |
301 | 227 |
302 void NEVER_INLINE checkThread() | 228 R operator()(Args... args) |
303 { | 229 { |
304 // Function with SameThreadAffinity, including SameThreadClosure | 230 DCHECK(m_threadChecker.CalledOnValidThread()); |
305 // created by WTF::bind() or blink::createSameThreadTask(), | 231 return m_callback.Run(std::forward<Args>(args)...); |
306 // must be called and destructed on the thread where it is created. | |
307 // If it is intended to be used cross-thread, use | |
308 // blink::threadSafeBind() or blink::createCrossThreadTask() instead. | |
309 RELEASE_ASSERT(m_createdThread == currentThread()); | |
310 } | 232 } |
311 | 233 |
312 private: | 234 private: |
313 const ThreadIdentifier m_createdThread; | 235 using MaybeThreadChecker = typename std::conditional< |
314 }; | 236 threadAffinity == SameThreadAffinity, |
315 #endif | 237 base::ThreadChecker, |
316 | 238 base::ThreadCheckerDoNothing>::type; |
317 template <FunctionThreadAffinity threadAffinity, typename BoundParametersTuple, typename FunctionWrapper, typename UnboundRunType> | 239 MaybeThreadChecker m_threadChecker; |
318 class PartBoundFunctionImpl; | 240 base::Callback<R(Args...)> m_callback; |
319 | |
320 template <FunctionThreadAffinity threadAffinity, typename... BoundParameters, ty pename FunctionWrapper, typename ResultType, typename... UnboundParameters> | |
321 class PartBoundFunctionImpl<threadAffinity, std::tuple<BoundParameters...>, Func tionWrapper, ResultType(UnboundParameters...)> final : public Function<ResultTyp e(UnboundParameters...), threadAffinity> { | |
322 public: | |
323 // We would like to use StorageTraits<UnboundParameters>... with StorageTrai ts defined as below in order to obtain | |
324 // storage traits of UnboundParameters, but unfortunately MSVC can't handle template using declarations correctly. | |
325 // So, sadly, we have write down the full type signature in all places where storage traits are needed. | |
326 // | |
327 // template <typename T> | |
328 // using StorageTraits = ParamStorageTraits<typename std::decay<T>::type>; | |
329 | |
330 // Note that BoundParameters can be const T&, T&& or a mix of these. | |
331 explicit PartBoundFunctionImpl(FunctionWrapper functionWrapper, BoundParamet ers... bound) | |
332 : m_functionWrapper(functionWrapper) | |
333 , m_bound(std::forward<BoundParameters>(bound)...) | |
334 { | |
335 } | |
336 | |
337 ResultType operator()(UnboundParameters... unbound) override | |
338 { | |
339 // What we really want to do is to call m_functionWrapper(m_bound..., un bound...), but to do that we need to | |
340 // pass a list of indices to a worker function template. | |
341 return callInternal(base::MakeIndexSequence<sizeof...(BoundParameters)>( ), std::forward<UnboundParameters>(unbound)...); | |
342 } | |
343 | |
344 private: | |
345 template <std::size_t... boundIndices, typename... IncomingUnboundParameters > | |
346 ResultType callInternal(const base::IndexSequence<boundIndices...>&, Incomin gUnboundParameters&&... unbound) | |
347 { | |
348 this->checkThread(); | |
349 // Get each element in m_bound, unwrap them, and call the function with the desired arguments. | |
350 using base::internal::Unwrap; | |
351 return m_functionWrapper(Unwrap(std::get<boundIndices>(m_bound))..., std ::forward<IncomingUnboundParameters>(unbound)...); | |
352 } | |
353 | |
354 FunctionWrapper m_functionWrapper; | |
355 std::tuple<typename ParamStorageTraits<typename std::decay<BoundParameters>: :type>::StorageType...> m_bound; | |
356 }; | 241 }; |
357 | 242 |
358 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> | 243 template <FunctionThreadAffinity threadAffinity, typename FunctionType, typename ... BoundParameters> |
359 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) | 244 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, threadAffinity>> bindInternal(FunctionType function, BoundParameters&&... b oundParameters) |
360 { | 245 { |
361 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound | 246 // Bound parameters' types are wrapped with std::tuple so we can pass two te mplate parameter packs (bound |
362 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th is type isn't actually created; | 247 // parameters and unbound) to PartBoundFunctionImpl. Note that a tuple of th is type isn't actually created; |
363 // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter | 248 // std::tuple<> is just for carrying the bound parameters' types. Any other class template taking a type parameter |
364 // pack can be used instead of std::tuple. std::tuple is used just because i t's most convenient for this purpose. | 249 // pack can be used instead of std::tuple. std::tuple is used just because i t's most convenient for this purpose. |
365 using UnboundRunType = base::MakeUnboundRunType<FunctionType, BoundParameter s...>; | 250 using UnboundRunType = base::MakeUnboundRunType<FunctionType, BoundParameter s...>; |
366 using BoundFunctionType = PartBoundFunctionImpl<threadAffinity, std::tuple<B oundParameters&&...>, FunctionWrapper<FunctionType>, UnboundRunType>; | 251 return wrapUnique(new Function<UnboundRunType, threadAffinity>(base::Bind(fu nction, typename ParamStorageTraits<typename std::decay<BoundParameters>::type>: :StorageType(std::forward<BoundParameters>(boundParameters))...))); |
Yuta Kitamura
2016/06/27 06:46:36
This line makes my brain cause a traffic jam... Le
tzik
2016/06/27 06:53:43
Agree. It's too long to look at a glance...
1. Yes
| |
367 return wrapUnique(new BoundFunctionType(FunctionWrapper<FunctionType>(functi on), std::forward<BoundParameters>(boundParameters)...)); | |
368 } | 252 } |
369 | 253 |
370 | |
371 | |
372 template <typename FunctionType, typename... BoundParameters> | 254 template <typename FunctionType, typename... BoundParameters> |
373 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, SameThreadAffinity>> bind(FunctionType function, BoundParameters&&... bound Parameters) | 255 std::unique_ptr<Function<base::MakeUnboundRunType<FunctionType, BoundParameters. ..>, SameThreadAffinity>> bind(FunctionType function, BoundParameters&&... bound Parameters) |
374 { | 256 { |
375 return bindInternal<SameThreadAffinity>(function, std::forward<BoundParamete rs>(boundParameters)...); | 257 return bindInternal<SameThreadAffinity>(function, std::forward<BoundParamete rs>(boundParameters)...); |
376 } | 258 } |
377 | 259 |
378 typedef Function<void(), SameThreadAffinity> SameThreadClosure; | 260 typedef Function<void(), SameThreadAffinity> SameThreadClosure; |
379 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; | 261 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; |
380 | 262 |
381 } // namespace WTF | 263 } // namespace WTF |
382 | 264 |
383 using WTF::bind; | 265 using WTF::bind; |
384 | 266 |
385 using WTF::passed; | 267 using WTF::passed; |
386 using WTF::unretained; | 268 using WTF::unretained; |
387 using WTF::crossThreadUnretained; | 269 using WTF::crossThreadUnretained; |
388 | 270 |
389 using WTF::Function; | 271 using WTF::Function; |
390 using WTF::SameThreadClosure; | 272 using WTF::SameThreadClosure; |
391 using WTF::CrossThreadClosure; | 273 using WTF::CrossThreadClosure; |
392 | 274 |
393 #endif // WTF_Functional_h | 275 #endif // WTF_Functional_h |
OLD | NEW |