Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: third_party/WebKit/Source/wtf/Functional.h

Issue 2092093002: Make WTF::Function be a base::Callback wrapper (5/5) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@03_wrap
Patch Set: rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/wtf/DEPS ('k') | third_party/WebKit/Source/wtf/FunctionalTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/DEPS ('k') | third_party/WebKit/Source/wtf/FunctionalTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698