OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
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, | |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
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 | |
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 | |
23 * THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | 4 |
26 #ifndef WTF_Functional_h | 5 #include "platform/wtf/Functional.h" |
27 #define WTF_Functional_h | |
28 | 6 |
29 #include "base/bind.h" | 7 // The contents of this header was moved to platform/wtf as part of |
30 #include "base/threading/thread_checker.h" | 8 // WTF migration project. See the following post for details: |
31 #include "wtf/Allocator.h" | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
32 #include "wtf/Assertions.h" | |
33 #include "wtf/PassRefPtr.h" | |
34 #include "wtf/PtrUtil.h" | |
35 #include "wtf/RefPtr.h" | |
36 #include "wtf/ThreadSafeRefCounted.h" | |
37 #include "wtf/TypeTraits.h" | |
38 #include <utility> | |
39 | |
40 namespace blink { | |
41 template <typename T> | |
42 class Member; | |
43 template <typename T> | |
44 class WeakMember; | |
45 } | |
46 | |
47 namespace WTF { | |
48 | |
49 // Functional.h provides a very simple way to bind a function pointer and | |
50 // arguments together into a function object that can be stored, copied and | |
51 // invoked, similar to boost::bind and std::bind in C++11. | |
52 | |
53 // Thread Safety: | |
54 // | |
55 // WTF::bind() and WTF::Closure should be used for same-thread closures | |
56 // only, i.e. the closures must be created, executed and destructed on | |
57 // the same thread. | |
58 // Use crossThreadBind() and CrossThreadClosure if the function/task is called | |
59 // or destructed on a (potentially) different thread from the current thread. | |
60 | |
61 // WTF::bind() and move semantics | |
62 // ============================== | |
63 // | |
64 // For unbound parameters (arguments supplied later on the bound functor | |
65 // directly), there are two ways to pass movable arguments: | |
66 // | |
67 // 1) Pass by rvalue reference. | |
68 // | |
69 // void yourFunction(Argument&& argument) { ... } | |
70 // std::unique_ptr<Function<void(Argument&&)>> functor = | |
71 // bind<Argument&&>(yourFunction); | |
72 // | |
73 // 2) Pass by value. | |
74 // | |
75 // void yourFunction(Argument argument) { ... } | |
76 // std::unique_ptr<Function<void(Argument)>> functor = | |
77 // bind<Argument>(yourFunction); | |
78 // | |
79 // Note that with the latter there will be *two* move constructions happening, | |
80 // because there needs to be at least one intermediary function call taking an | |
81 // argument of type "Argument" (i.e. passed by value). The former case does not | |
82 // require any move constructions inbetween. | |
83 // | |
84 // For bound parameters (arguments supplied on the creation of a functor), you | |
85 // can move your argument into the internal storage of the functor by supplying | |
86 // an rvalue to that argument (this is done in wrap() of ParamStorageTraits). | |
87 // However, to make the functor be able to get called multiple times, the | |
88 // stored object does not get moved out automatically when the underlying | |
89 // function is actually invoked. If you want to make an argument "auto-passed", | |
90 // you can do so by wrapping your bound argument with WTF::passed() function, as | |
91 // shown below: | |
92 // | |
93 // void yourFunction(Argument argument) | |
94 // { | |
95 // // |argument| is passed from the internal storage of functor. | |
96 // ... | |
97 // } | |
98 // | |
99 // ... | |
100 // std::unique_ptr<Function<void()>> functor = bind(yourFunction, | |
101 // WTF::passed(Argument())); | |
102 // ... | |
103 // (*functor)(); | |
104 // | |
105 // The underlying function must receive the argument wrapped by WTF::passed() by | |
106 // rvalue reference or by value. | |
107 // | |
108 // Obviously, if you create a functor this way, you shouldn't call the functor | |
109 // twice or more; after the second call, the passed argument may be invalid. | |
110 | |
111 enum FunctionThreadAffinity { CrossThreadAffinity, SameThreadAffinity }; | |
112 | |
113 template <typename T> | |
114 class PassedWrapper final { | |
115 public: | |
116 explicit PassedWrapper(T&& scoper) : m_scoper(std::move(scoper)) {} | |
117 PassedWrapper(PassedWrapper&& other) : m_scoper(std::move(other.m_scoper)) {} | |
118 T moveOut() const { return std::move(m_scoper); } | |
119 | |
120 private: | |
121 mutable T m_scoper; | |
122 }; | |
123 | |
124 template <typename T> | |
125 PassedWrapper<T> passed(T&& value) { | |
126 static_assert( | |
127 !std::is_reference<T>::value, | |
128 "You must pass an rvalue to WTF::passed() so it can be moved. Add " | |
129 "std::move() if necessary."); | |
130 static_assert(!std::is_const<T>::value, | |
131 "|value| must not be const so it can be moved."); | |
132 return PassedWrapper<T>(std::move(value)); | |
133 } | |
134 | |
135 template <typename T, FunctionThreadAffinity threadAffinity> | |
136 class UnretainedWrapper final { | |
137 public: | |
138 explicit UnretainedWrapper(T* ptr) : m_ptr(ptr) {} | |
139 T* value() const { return m_ptr; } | |
140 | |
141 private: | |
142 T* m_ptr; | |
143 }; | |
144 | |
145 template <typename T> | |
146 UnretainedWrapper<T, SameThreadAffinity> unretained(T* value) { | |
147 static_assert(!WTF::IsGarbageCollectedType<T>::value, | |
148 "WTF::unretained() + GCed type is forbidden"); | |
149 return UnretainedWrapper<T, SameThreadAffinity>(value); | |
150 } | |
151 | |
152 template <typename T> | |
153 UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) { | |
154 static_assert(!WTF::IsGarbageCollectedType<T>::value, | |
155 "crossThreadUnretained() + GCed type is forbidden"); | |
156 return UnretainedWrapper<T, CrossThreadAffinity>(value); | |
157 } | |
158 | |
159 template <typename T> | |
160 struct ParamStorageTraits { | |
161 typedef T StorageType; | |
162 | |
163 static_assert(!std::is_pointer<T>::value, | |
164 "Raw pointers are not allowed to bind into WTF::Function. Wrap " | |
165 "it with either wrapPersistent, wrapWeakPersistent, " | |
166 "wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, " | |
167 "RefPtr or unretained."); | |
168 static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && | |
169 !IsSubclassOfTemplate<T, blink::WeakMember>::value, | |
170 "Member and WeakMember are not allowed to bind into " | |
171 "WTF::Function. Wrap it with either wrapPersistent, " | |
172 "wrapWeakPersistent, wrapCrossThreadPersistent or " | |
173 "wrapCrossThreadWeakPersistent."); | |
174 }; | |
175 | |
176 template <typename T> | |
177 struct ParamStorageTraits<PassRefPtr<T>> { | |
178 typedef RefPtr<T> StorageType; | |
179 }; | |
180 | |
181 template <typename T> | |
182 struct ParamStorageTraits<RefPtr<T>> { | |
183 typedef RefPtr<T> StorageType; | |
184 }; | |
185 | |
186 template <typename> | |
187 class RetainPtr; | |
188 | |
189 template <typename T> | |
190 struct ParamStorageTraits<RetainPtr<T>> { | |
191 typedef RetainPtr<T> StorageType; | |
192 }; | |
193 | |
194 template <typename T> | |
195 struct ParamStorageTraits<PassedWrapper<T>> { | |
196 typedef PassedWrapper<T> StorageType; | |
197 }; | |
198 | |
199 template <typename T, FunctionThreadAffinity threadAffinity> | |
200 struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { | |
201 typedef UnretainedWrapper<T, threadAffinity> StorageType; | |
202 }; | |
203 | |
204 template <typename Signature, | |
205 FunctionThreadAffinity threadAffinity = SameThreadAffinity> | |
206 class Function; | |
207 | |
208 template <typename R, typename... Args, FunctionThreadAffinity threadAffinity> | |
209 class Function<R(Args...), threadAffinity> { | |
210 USING_FAST_MALLOC(Function); | |
211 WTF_MAKE_NONCOPYABLE(Function); | |
212 | |
213 public: | |
214 Function(base::Callback<R(Args...)> callback) | |
215 : m_callback(std::move(callback)) {} | |
216 | |
217 ~Function() { DCHECK(m_threadChecker.CalledOnValidThread()); } | |
218 | |
219 R operator()(Args... args) { | |
220 DCHECK(m_threadChecker.CalledOnValidThread()); | |
221 return m_callback.Run(std::forward<Args>(args)...); | |
222 } | |
223 | |
224 bool isCancelled() const { return m_callback.IsCancelled(); } | |
225 | |
226 friend base::Callback<R(Args...)> convertToBaseCallback( | |
227 std::unique_ptr<Function> function) { | |
228 if (function) | |
229 return std::move(function->m_callback); | |
230 return base::Callback<R(Args...)>(); | |
231 } | |
232 | |
233 private: | |
234 using MaybeThreadChecker = | |
235 typename std::conditional<threadAffinity == SameThreadAffinity, | |
236 base::ThreadChecker, | |
237 base::ThreadCheckerDoNothing>::type; | |
238 MaybeThreadChecker m_threadChecker; | |
239 base::Callback<R(Args...)> m_callback; | |
240 }; | |
241 | |
242 template <FunctionThreadAffinity threadAffinity, | |
243 typename FunctionType, | |
244 typename... BoundParameters> | |
245 std::unique_ptr< | |
246 Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, | |
247 threadAffinity>> | |
248 bindInternal(FunctionType function, BoundParameters&&... boundParameters) { | |
249 using UnboundRunType = | |
250 base::MakeUnboundRunType<FunctionType, BoundParameters...>; | |
251 return WTF::wrapUnique(new Function<UnboundRunType, | |
252 threadAffinity>(base::Bind( | |
253 function, | |
254 typename ParamStorageTraits<typename std::decay<BoundParameters>::type>:: | |
255 StorageType(std::forward<BoundParameters>(boundParameters))...))); | |
256 } | |
257 | |
258 template <typename FunctionType, typename... BoundParameters> | |
259 std::unique_ptr< | |
260 Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, | |
261 SameThreadAffinity>> | |
262 bind(FunctionType function, BoundParameters&&... boundParameters) { | |
263 return bindInternal<SameThreadAffinity>( | |
264 function, std::forward<BoundParameters>(boundParameters)...); | |
265 } | |
266 | |
267 typedef Function<void(), SameThreadAffinity> Closure; | |
268 typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; | |
269 | |
270 } // namespace WTF | |
271 | |
272 namespace base { | |
273 | |
274 template <typename T> | |
275 struct BindUnwrapTraits<WTF::RefPtr<T>> { | |
276 static T* Unwrap(const WTF::RefPtr<T>& wrapped) { return wrapped.get(); } | |
277 }; | |
278 | |
279 template <typename T> | |
280 struct BindUnwrapTraits<WTF::PassedWrapper<T>> { | |
281 static T Unwrap(const WTF::PassedWrapper<T>& wrapped) { | |
282 return wrapped.moveOut(); | |
283 } | |
284 }; | |
285 | |
286 template <typename T, WTF::FunctionThreadAffinity threadAffinity> | |
287 struct BindUnwrapTraits<WTF::UnretainedWrapper<T, threadAffinity>> { | |
288 static T* Unwrap(const WTF::UnretainedWrapper<T, threadAffinity>& wrapped) { | |
289 return wrapped.value(); | |
290 } | |
291 }; | |
292 | |
293 } // namespace base | |
294 | |
295 using WTF::crossThreadUnretained; | |
296 | |
297 using WTF::Function; | |
298 using WTF::CrossThreadClosure; | |
299 | |
300 #endif // WTF_Functional_h | |
OLD | NEW |