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