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// This file contains utility functions and classes that help the 6// implementation, and management of the Callback objects. 7 8#ifndef BASE_CALLBACK_INTERNAL_H_ 9#define BASE_CALLBACK_INTERNAL_H_ 10#pragma once 11 12#include <stddef.h> 13 14#include "base/base_api.h" 15#include "base/memory/ref_counted.h" 16 17namespace base { 18namespace internal { 19 20// InvokerStorageBase is used to provide an opaque handle that the Callback 21// class can use to represent a function object with bound arguments. It 22// behaves as an existential type that is used by a corresponding 23// DoInvoke function to perform the function execution. This allows 24// us to shield the Callback class from the types of the bound argument via 25// "type erasure." 26class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> { 27 protected: 28 friend class RefCountedThreadSafe<InvokerStorageBase>; 29 virtual ~InvokerStorageBase() {} 30}; 31 32// This structure exists purely to pass the returned |invoker_storage_| from 33// Bind() to Callback while avoiding an extra AddRef/Release() pair. 34// 35// To do this, the constructor of Callback<> must take a const-ref. The 36// reference must be to a const object otherwise the compiler will emit a 37// warning about taking a reference to a temporary. 38// 39// Unfortunately, this means that the internal |invoker_storage_| field must 40// be made mutable. 41template <typename T> 42struct InvokerStorageHolder { 43 explicit InvokerStorageHolder(T* invoker_storage) 44 : invoker_storage_(invoker_storage) { 45 } 46 47 mutable scoped_refptr<InvokerStorageBase> invoker_storage_; 48}; 49 50template <typename T> 51InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) { 52 return InvokerStorageHolder<T>(o); 53} 54 55// Holds the Callback methods that don't require specialization to reduce 56// template bloat. 57class BASE_API CallbackBase { 58 public: 59 // Returns true if Callback is null (doesn't refer to anything). 60 bool is_null() const; 61 62 // Returns the Callback into an uninitalized state. 63 void Reset(); 64 65 bool Equals(const CallbackBase& other) const; 66 67 protected: 68 // In C++, it is safe to cast function pointers to function pointers of 69 // another type. It is not okay to use void*. We create a InvokeFuncStorage 70 // that that can store our function pointer, and then cast it back to 71 // the original type on usage. 72 typedef void(*InvokeFuncStorage)(void); 73 74 CallbackBase(InvokeFuncStorage polymorphic_invoke, 75 scoped_refptr<InvokerStorageBase>* invoker_storage); 76 77 // Force the destructor to be instaniated inside this translation unit so 78 // that our subclasses will not get inlined versions. Avoids more template 79 // bloat. 80 ~CallbackBase(); 81 82 scoped_refptr<InvokerStorageBase> invoker_storage_; 83 InvokeFuncStorage polymorphic_invoke_; 84}; 85 86// This is a typetraits object that's used to take an argument type, and 87// extract a suitable type for storing and forwarding arguments. 88// 89// In particular, it strips off references, and converts arrays to 90// pointers for storage; and it avoids accidentally trying to create a 91// "reference of a reference" if the argument is a reference type. 92// 93// This array type becomes an issue for storage because we are passing bound 94// parameters by const reference. In this case, we end up passing an actual 95// array type in the initializer list which C++ does not allow. This will 96// break passing of C-string literals. 97template <typename T> 98struct ParamTraits { 99 typedef const T& ForwardType; 100 typedef T StorageType; 101}; 102 103// The Storage should almost be impossible to trigger unless someone manually 104// specifies type of the bind parameters. However, in case they do, 105// this will guard against us accidentally storing a reference parameter. 106// 107// The ForwardType should only be used for unbound arguments. 108template <typename T> 109struct ParamTraits<T&> { 110 typedef T& ForwardType; 111 typedef T StorageType; 112}; 113 114// Note that for array types, we implicitly add a const in the conversion. This 115// means that it is not possible to bind array arguments to functions that take 116// a non-const pointer. Trying to specialize the template based on a "const 117// T[n]" does not seem to match correctly, so we are stuck with this 118// restriction. 119template <typename T, size_t n> 120struct ParamTraits<T[n]> { 121 typedef const T* ForwardType; 122 typedef const T* StorageType; 123}; 124 125// See comment for ParamTraits<T[n]>. 126template <typename T> 127struct ParamTraits<T[]> { 128 typedef const T* ForwardType; 129 typedef const T* StorageType; 130}; 131 132} // namespace internal 133} // namespace base 134 135#endif // BASE_CALLBACK_INTERNAL_H_ 136