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.
5 // This file contains utility functions and classes that help the
6 // implementation, and management of the Callback objects.
8 #ifndef BASE_CALLBACK_INTERNAL_H_
9 #define BASE_CALLBACK_INTERNAL_H_
14 #include "base/base_export.h"
15 #include "base/memory/ref_counted.h"
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
26 class InvokerStorageBase
: public RefCountedThreadSafe
<InvokerStorageBase
> {
28 friend class RefCountedThreadSafe
<InvokerStorageBase
>;
29 virtual ~InvokerStorageBase() {}
32 // This structure exists purely to pass the returned |invoker_storage_| from
33 // Bind() to Callback while avoiding an extra AddRef/Release() pair.
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.
39 // Unfortunately, this means that the internal |invoker_storage_| field must
42 struct InvokerStorageHolder
{
43 explicit InvokerStorageHolder(T
* invoker_storage
)
44 : invoker_storage_(invoker_storage
) {
47 mutable scoped_refptr
<InvokerStorageBase
> invoker_storage_
;
51 InvokerStorageHolder
<T
> MakeInvokerStorageHolder(T
* o
) {
52 return InvokerStorageHolder
<T
>(o
);
55 // Holds the Callback methods that don't require specialization to reduce
57 class BASE_EXPORT CallbackBase
{
59 // Returns true if Callback is null (doesn't refer to anything).
62 // Returns the Callback into an uninitialized state.
66 // In C++, it is safe to cast function pointers to function pointers of
67 // another type. It is not okay to use void*. We create a InvokeFuncStorage
68 // that that can store our function pointer, and then cast it back to
69 // the original type on usage.
70 typedef void(*InvokeFuncStorage
)(void);
72 // Returns true if this callback equals |other|. |other| may be null.
73 bool Equals(const CallbackBase
& other
) const;
75 CallbackBase(InvokeFuncStorage polymorphic_invoke
,
76 scoped_refptr
<InvokerStorageBase
>* invoker_storage
);
78 // Force the destructor to be instantiated inside this translation unit so
79 // that our subclasses will not get inlined versions. Avoids more template
83 scoped_refptr
<InvokerStorageBase
> invoker_storage_
;
84 InvokeFuncStorage polymorphic_invoke_
;
87 // This is a typetraits object that's used to take an argument type, and
88 // extract a suitable type for storing and forwarding arguments.
90 // In particular, it strips off references, and converts arrays to
91 // pointers for storage; and it avoids accidentally trying to create a
92 // "reference of a reference" if the argument is a reference type.
94 // This array type becomes an issue for storage because we are passing bound
95 // parameters by const reference. In this case, we end up passing an actual
96 // array type in the initializer list which C++ does not allow. This will
97 // break passing of C-string literals.
100 typedef const T
& ForwardType
;
101 typedef T StorageType
;
104 // The Storage should almost be impossible to trigger unless someone manually
105 // specifies type of the bind parameters. However, in case they do,
106 // this will guard against us accidentally storing a reference parameter.
108 // The ForwardType should only be used for unbound arguments.
109 template <typename T
>
110 struct ParamTraits
<T
&> {
111 typedef T
& ForwardType
;
112 typedef T StorageType
;
115 // Note that for array types, we implicitly add a const in the conversion. This
116 // means that it is not possible to bind array arguments to functions that take
117 // a non-const pointer. Trying to specialize the template based on a "const
118 // T[n]" does not seem to match correctly, so we are stuck with this
120 template <typename T
, size_t n
>
121 struct ParamTraits
<T
[n
]> {
122 typedef const T
* ForwardType
;
123 typedef const T
* StorageType
;
126 // See comment for ParamTraits<T[n]>.
127 template <typename T
>
128 struct ParamTraits
<T
[]> {
129 typedef const T
* ForwardType
;
130 typedef const T
* StorageType
;
133 } // namespace internal
136 #endif // BASE_CALLBACK_INTERNAL_H_