1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_BIND_INTERNAL_H_ 6 #define BASE_BIND_INTERNAL_H_ 7 8 #include <stddef.h> 9 10 #include <type_traits> 11 12 #include "base/bind_helpers.h" 13 #include "base/callback_internal.h" 14 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/template_util.h" 17 #include "base/tuple.h" 18 #include "build/build_config.h" 19 20 #if defined(OS_WIN) 21 #include "base/bind_internal_win.h" 22 #endif 23 24 namespace base { 25 namespace internal { 26 27 // See base/callback.h for user documentation. 28 // 29 // 30 // CONCEPTS: 31 // Runnable -- A type (really a type class) that has a single Run() method 32 // and a RunType typedef that corresponds to the type of Run(). 33 // A Runnable can declare that it should treated like a method 34 // call by including a typedef named IsMethod. The value of 35 // this typedef is NOT inspected, only the existence. When a 36 // Runnable declares itself a method, Bind() will enforce special 37 // refcounting + WeakPtr handling semantics for the first 38 // parameter which is expected to be an object. 39 // Functor -- A copyable type representing something that should be called. 40 // All function pointers, Callback<>, and Runnables are functors 41 // even if the invocation syntax differs. 42 // RunType -- A function type (as opposed to function _pointer_ type) for 43 // a Run() function. Usually just a convenience typedef. 44 // (Bound)Args -- A set of types that stores the arguments. 45 // 46 // Types: 47 // RunnableAdapter<> -- Wraps the various "function" pointer types into an 48 // object that adheres to the Runnable interface. 49 // ForceVoidReturn<> -- Helper class for translating function signatures to 50 // equivalent forms with a "void" return type. 51 // FunctorTraits<> -- Type traits used determine the correct RunType and 52 // RunnableType for a Functor. This is where function 53 // signature adapters are applied. 54 // MakeRunnable<> -- Takes a Functor and returns an object in the Runnable 55 // type class that represents the underlying Functor. 56 // InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. 57 // Handle the differing syntaxes needed for WeakPtr<> 58 // support, and for ignoring return values. This is separate 59 // from Invoker to avoid creating multiple version of 60 // Invoker<>. 61 // Invoker<> -- Unwraps the curried parameters and executes the Runnable. 62 // BindState<> -- Stores the curried parameters, and is the main entry point 63 // into the Bind() system, doing most of the type resolution. 64 // There are ARITY BindState types. 65 66 // HasNonConstReferenceParam selects true_type when any of the parameters in 67 // |Sig| is a non-const reference. 68 // Implementation note: This non-specialized case handles zero-arity case only. 69 // Non-zero-arity cases should be handled by the specialization below. 70 template <typename List> 71 struct HasNonConstReferenceItem : false_type {}; 72 73 // Implementation note: Select true_type if the first parameter is a non-const 74 // reference. Otherwise, skip the first parameter and check rest of parameters 75 // recursively. 76 template <typename T, typename... Args> 77 struct HasNonConstReferenceItem<TypeList<T, Args...>> 78 : std::conditional<is_non_const_reference<T>::value, 79 true_type, 80 HasNonConstReferenceItem<TypeList<Args...>>>::type {}; 81 82 // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw 83 // pointer to a RefCounted type. 84 // Implementation note: This non-specialized case handles zero-arity case only. 85 // Non-zero-arity cases should be handled by the specialization below. 86 template <typename... Args> 87 struct HasRefCountedTypeAsRawPtr : false_type {}; 88 89 // Implementation note: Select true_type if the first parameter is a raw pointer 90 // to a RefCounted type. Otherwise, skip the first parameter and check rest of 91 // parameters recursively. 92 template <typename T, typename... Args> 93 struct HasRefCountedTypeAsRawPtr<T, Args...> 94 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value, 95 true_type, 96 HasRefCountedTypeAsRawPtr<Args...>>::type {}; 97 98 // BindsArrayToFirstArg selects true_type when |is_method| is true and the first 99 // item of |Args| is an array type. 100 // Implementation note: This non-specialized case handles !is_method case and 101 // zero-arity case only. Other cases should be handled by the specialization 102 // below. 103 template <bool is_method, typename... Args> 104 struct BindsArrayToFirstArg : false_type {}; 105 106 template <typename T, typename... Args> 107 struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {}; 108 109 // HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except 110 // when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument. 111 // Implementation note: This non-specialized case handles !is_method case and 112 // zero-arity case only. Other cases should be handled by the specialization 113 // below. 114 template <bool is_method, typename... Args> 115 struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {}; 116 117 template <typename T, typename... Args> 118 struct HasRefCountedParamAsRawPtr<true, T, Args...> 119 : HasRefCountedTypeAsRawPtr<Args...> {}; 120 121 // RunnableAdapter<> 122 // 123 // The RunnableAdapter<> templates provide a uniform interface for invoking 124 // a function pointer, method pointer, or const method pointer. The adapter 125 // exposes a Run() method with an appropriate signature. Using this wrapper 126 // allows for writing code that supports all three pointer types without 127 // undue repetition. Without it, a lot of code would need to be repeated 3 128 // times. 129 // 130 // For method pointers and const method pointers the first argument to Run() 131 // is considered to be the received of the method. This is similar to STL's 132 // mem_fun(). 133 // 134 // This class also exposes a RunType typedef that is the function type of the 135 // Run() function. 136 // 137 // If and only if the wrapper contains a method or const method pointer, an 138 // IsMethod typedef is exposed. The existence of this typedef (NOT the value) 139 // marks that the wrapper should be considered a method wrapper. 140 141 template <typename Functor> 142 class RunnableAdapter; 143 144 // Function. 145 template <typename R, typename... Args> 146 class RunnableAdapter<R(*)(Args...)> { 147 public: 148 // MSVC 2013 doesn't support Type Alias of function types. 149 // Revisit this after we update it to newer version. 150 typedef R RunType(Args...); 151 152 explicit RunnableAdapter(R(*function)(Args...)) 153 : function_(function) { 154 } 155 156 R Run(typename CallbackParamTraits<Args>::ForwardType... args) { 157 return function_(CallbackForward(args)...); 158 } 159 160 private: 161 R (*function_)(Args...); 162 }; 163 164 // Method. 165 template <typename R, typename T, typename... Args> 166 class RunnableAdapter<R(T::*)(Args...)> { 167 public: 168 // MSVC 2013 doesn't support Type Alias of function types. 169 // Revisit this after we update it to newer version. 170 typedef R RunType(T*, Args...); 171 using IsMethod = true_type; 172 173 explicit RunnableAdapter(R(T::*method)(Args...)) 174 : method_(method) { 175 } 176 177 R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) { 178 return (object->*method_)(CallbackForward(args)...); 179 } 180 181 private: 182 R (T::*method_)(Args...); 183 }; 184 185 // Const Method. 186 template <typename R, typename T, typename... Args> 187 class RunnableAdapter<R(T::*)(Args...) const> { 188 public: 189 using RunType = R(const T*, Args...); 190 using IsMethod = true_type; 191 192 explicit RunnableAdapter(R(T::*method)(Args...) const) 193 : method_(method) { 194 } 195 196 R Run(const T* object, 197 typename CallbackParamTraits<Args>::ForwardType... args) { 198 return (object->*method_)(CallbackForward(args)...); 199 } 200 201 private: 202 R (T::*method_)(Args...) const; 203 }; 204 205 206 // ForceVoidReturn<> 207 // 208 // Set of templates that support forcing the function return type to void. 209 template <typename Sig> 210 struct ForceVoidReturn; 211 212 template <typename R, typename... Args> 213 struct ForceVoidReturn<R(Args...)> { 214 // MSVC 2013 doesn't support Type Alias of function types. 215 // Revisit this after we update it to newer version. 216 typedef void RunType(Args...); 217 }; 218 219 220 // FunctorTraits<> 221 // 222 // See description at top of file. 223 template <typename T> 224 struct FunctorTraits { 225 using RunnableType = RunnableAdapter<T>; 226 using RunType = typename RunnableType::RunType; 227 }; 228 229 template <typename T> 230 struct FunctorTraits<IgnoreResultHelper<T>> { 231 using RunnableType = typename FunctorTraits<T>::RunnableType; 232 using RunType = 233 typename ForceVoidReturn<typename RunnableType::RunType>::RunType; 234 }; 235 236 template <typename T> 237 struct FunctorTraits<Callback<T>> { 238 using RunnableType = Callback<T> ; 239 using RunType = typename Callback<T>::RunType; 240 }; 241 242 243 // MakeRunnable<> 244 // 245 // Converts a passed in functor to a RunnableType using type inference. 246 247 template <typename T> 248 typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { 249 return RunnableAdapter<T>(t); 250 } 251 252 template <typename T> 253 typename FunctorTraits<T>::RunnableType 254 MakeRunnable(const IgnoreResultHelper<T>& t) { 255 return MakeRunnable(t.functor_); 256 } 257 258 template <typename T> 259 const typename FunctorTraits<Callback<T>>::RunnableType& 260 MakeRunnable(const Callback<T>& t) { 261 DCHECK(!t.is_null()); 262 return t; 263 } 264 265 266 // InvokeHelper<> 267 // 268 // There are 3 logical InvokeHelper<> specializations: normal, void-return, 269 // WeakCalls. 270 // 271 // The normal type just calls the underlying runnable. 272 // 273 // We need a InvokeHelper to handle void return types in order to support 274 // IgnoreResult(). Normally, if the Runnable's RunType had a void return, 275 // the template system would just accept "return functor.Run()" ignoring 276 // the fact that a void function is being used with return. This piece of 277 // sugar breaks though when the Runnable's RunType is not void. Thus, we 278 // need a partial specialization to change the syntax to drop the "return" 279 // from the invocation call. 280 // 281 // WeakCalls similarly need special syntax that is applied to the first 282 // argument to check if they should no-op themselves. 283 template <bool IsWeakCall, typename ReturnType, typename Runnable, 284 typename ArgsType> 285 struct InvokeHelper; 286 287 template <typename ReturnType, typename Runnable, typename... Args> 288 struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> { 289 static ReturnType MakeItSo(Runnable runnable, Args... args) { 290 return runnable.Run(CallbackForward(args)...); 291 } 292 }; 293 294 template <typename Runnable, typename... Args> 295 struct InvokeHelper<false, void, Runnable, TypeList<Args...>> { 296 static void MakeItSo(Runnable runnable, Args... args) { 297 runnable.Run(CallbackForward(args)...); 298 } 299 }; 300 301 template <typename Runnable, typename BoundWeakPtr, typename... Args> 302 struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> { 303 static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) { 304 if (!weak_ptr.get()) { 305 return; 306 } 307 runnable.Run(weak_ptr.get(), CallbackForward(args)...); 308 } 309 }; 310 311 #if !defined(_MSC_VER) 312 313 template <typename ReturnType, typename Runnable, typename ArgsType> 314 struct InvokeHelper<true, ReturnType, Runnable, ArgsType> { 315 // WeakCalls are only supported for functions with a void return type. 316 // Otherwise, the function result would be undefined if the the WeakPtr<> 317 // is invalidated. 318 static_assert(is_void<ReturnType>::value, 319 "weak_ptrs can only bind to methods without return values"); 320 }; 321 322 #endif 323 324 // Invoker<> 325 // 326 // See description at the top of the file. 327 template <typename BoundIndices, 328 typename StorageType, typename Unwrappers, 329 typename InvokeHelperType, typename UnboundForwardRunType> 330 struct Invoker; 331 332 template <size_t... bound_indices, 333 typename StorageType, 334 typename... Unwrappers, 335 typename InvokeHelperType, 336 typename R, 337 typename... UnboundForwardArgs> 338 struct Invoker<IndexSequence<bound_indices...>, 339 StorageType, TypeList<Unwrappers...>, 340 InvokeHelperType, R(UnboundForwardArgs...)> { 341 static R Run(BindStateBase* base, 342 UnboundForwardArgs... unbound_args) { 343 StorageType* storage = static_cast<StorageType*>(base); 344 // Local references to make debugger stepping easier. If in a debugger, 345 // you really want to warp ahead and step through the 346 // InvokeHelper<>::MakeItSo() call below. 347 return InvokeHelperType::MakeItSo( 348 storage->runnable_, 349 Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))..., 350 CallbackForward(unbound_args)...); 351 } 352 }; 353 354 355 // BindState<> 356 // 357 // This stores all the state passed into Bind() and is also where most 358 // of the template resolution magic occurs. 359 // 360 // Runnable is the functor we are binding arguments to. 361 // RunType is type of the Run() function that the Invoker<> should use. 362 // Normally, this is the same as the RunType of the Runnable, but it can 363 // be different if an adapter like IgnoreResult() has been used. 364 // 365 // BoundArgs contains the storage type for all the bound arguments. 366 template <typename Runnable, typename RunType, typename... BoundArgs> 367 struct BindState; 368 369 template <typename Runnable, 370 typename R, 371 typename... Args, 372 typename... BoundArgs> 373 struct BindState<Runnable, R(Args...), BoundArgs...> final 374 : public BindStateBase { 375 private: 376 using StorageType = BindState<Runnable, R(Args...), BoundArgs...>; 377 using RunnableType = Runnable; 378 379 // true_type if Runnable is a method invocation and the first bound argument 380 // is a WeakPtr. 381 using IsWeakCall = 382 IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>; 383 384 using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>; 385 using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>; 386 using UnboundForwardArgs = DropTypeListItem< 387 sizeof...(BoundArgs), 388 TypeList<typename CallbackParamTraits<Args>::ForwardType...>>; 389 using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>; 390 391 using InvokeHelperArgs = ConcatTypeLists< 392 TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>, 393 UnboundForwardArgs>; 394 using InvokeHelperType = 395 InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>; 396 397 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>; 398 399 public: 400 using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers, 401 InvokeHelperType, UnboundForwardRunType>; 402 using UnboundRunType = MakeFunctionType<R, UnboundArgs>; 403 404 BindState(const Runnable& runnable, const BoundArgs&... bound_args) 405 : BindStateBase(&Destroy), 406 runnable_(runnable), 407 ref_(bound_args...), 408 bound_args_(bound_args...) {} 409 410 RunnableType runnable_; 411 MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_; 412 Tuple<BoundArgs...> bound_args_; 413 414 private: 415 ~BindState() {} 416 417 static void Destroy(BindStateBase* self) { 418 delete static_cast<BindState*>(self); 419 } 420 }; 421 422 } // namespace internal 423 } // namespace base 424 425 #endif // BASE_BIND_INTERNAL_H_ 426