| 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 |