• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 namespace base {
18 namespace 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."
26 class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> {
27  protected:
28   friend class RefCountedThreadSafe<InvokerStorageBase>;
~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.
41 template <typename T>
42 struct InvokerStorageHolder {
InvokerStorageHolderInvokerStorageHolder43   explicit InvokerStorageHolder(T* invoker_storage)
44       : invoker_storage_(invoker_storage) {
45   }
46 
47   mutable scoped_refptr<InvokerStorageBase> invoker_storage_;
48 };
49 
50 template <typename T>
MakeInvokerStorageHolder(T * o)51 InvokerStorageHolder<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.
57 class 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.
97 template <typename T>
98 struct 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.
108 template <typename T>
109 struct 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.
119 template <typename T, size_t n>
120 struct ParamTraits<T[n]> {
121   typedef const T* ForwardType;
122   typedef const T* StorageType;
123 };
124 
125 // See comment for ParamTraits<T[n]>.
126 template <typename T>
127 struct 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