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 24namespace base { 25namespace 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. 70template <typename List> 71struct HasNonConstReferenceItem : std::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. 76template <typename T, typename... Args> 77struct HasNonConstReferenceItem<TypeList<T, Args...>> 78 : std::conditional<is_non_const_reference<T>::value, 79 std::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. 86template <typename... Args> 87struct HasRefCountedTypeAsRawPtr : std::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. 92template <typename T, typename... Args> 93struct HasRefCountedTypeAsRawPtr<T, Args...> 94 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value, 95 std::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. 103template <bool is_method, typename... Args> 104struct BindsArrayToFirstArg : std::false_type {}; 105 106template <typename T, typename... Args> 107struct BindsArrayToFirstArg<true, T, Args...> : std::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. 114template <bool is_method, typename... Args> 115struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {}; 116 117template <typename T, typename... Args> 118struct 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 141template <typename Functor> 142class RunnableAdapter; 143 144// Function. 145template <typename R, typename... Args> 146class 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. 165template <typename R, typename T, typename... Args> 166class 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 = std::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. 186template <typename R, typename T, typename... Args> 187class RunnableAdapter<R(T::*)(Args...) const> { 188 public: 189 using RunType = R(const T*, Args...); 190 using IsMethod = std::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. 209template <typename Sig> 210struct ForceVoidReturn; 211 212template <typename R, typename... Args> 213struct 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. 223template <typename T> 224struct FunctorTraits { 225 using RunnableType = RunnableAdapter<T>; 226 using RunType = typename RunnableType::RunType; 227}; 228 229template <typename T> 230struct FunctorTraits<IgnoreResultHelper<T>> { 231 using RunnableType = typename FunctorTraits<T>::RunnableType; 232 using RunType = 233 typename ForceVoidReturn<typename RunnableType::RunType>::RunType; 234}; 235 236template <typename T> 237struct 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 247template <typename T> 248typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { 249 return RunnableAdapter<T>(t); 250} 251 252template <typename T> 253typename FunctorTraits<T>::RunnableType 254MakeRunnable(const IgnoreResultHelper<T>& t) { 255 return MakeRunnable(t.functor_); 256} 257 258template <typename T> 259const typename FunctorTraits<Callback<T>>::RunnableType& 260MakeRunnable(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. 283template <bool IsWeakCall, typename ReturnType, typename Runnable, 284 typename ArgsType> 285struct InvokeHelper; 286 287template <typename ReturnType, typename Runnable, typename... Args> 288struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> { 289 static ReturnType MakeItSo(Runnable runnable, Args... args) { 290 return runnable.Run(CallbackForward(args)...); 291 } 292}; 293 294template <typename Runnable, typename... Args> 295struct InvokeHelper<false, void, Runnable, TypeList<Args...>> { 296 static void MakeItSo(Runnable runnable, Args... args) { 297 runnable.Run(CallbackForward(args)...); 298 } 299}; 300 301template <typename Runnable, typename BoundWeakPtr, typename... Args> 302struct 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 313template <typename ReturnType, typename Runnable, typename ArgsType> 314struct 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(std::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. 327template <typename BoundIndices, 328 typename StorageType, typename Unwrappers, 329 typename InvokeHelperType, typename UnboundForwardRunType> 330struct Invoker; 331 332template <size_t... bound_indices, 333 typename StorageType, 334 typename... Unwrappers, 335 typename InvokeHelperType, 336 typename R, 337 typename... UnboundForwardArgs> 338struct 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. 366template <typename Runnable, typename RunType, typename... BoundArgs> 367struct BindState; 368 369template <typename Runnable, 370 typename R, 371 typename... Args, 372 typename... BoundArgs> 373struct 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