blob: 4f0736f0eb6ae4556c52396bc9b6f7a39a918daf [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]2edc2862011-04-04 18:04:3712#include <stddef.h>
13
[email protected]0bea7252011-08-05 15:34:0014#include "base/base_export.h"
[email protected]3b63f8f42011-03-28 01:54:1515#include "base/memory/ref_counted.h"
[email protected]b38d3572011-02-15 01:27:3816
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
[email protected]59eff912011-02-18 23:29:3155// Holds the Callback methods that don't require specialization to reduce
56// template bloat.
[email protected]0bea7252011-08-05 15:34:0057class BASE_EXPORT CallbackBase {
[email protected]59eff912011-02-18 23:29:3158 public:
59 // Returns true if Callback is null (doesn't refer to anything).
60 bool is_null() const;
61
[email protected]1c35a482011-10-25 23:19:5162 // Returns the Callback into an uninitialized state.
[email protected]59eff912011-02-18 23:29:3163 void Reset();
64
[email protected]481915a772011-09-10 03:14:3565 protected:
[email protected]59eff912011-02-18 23:29:3166 // 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
[email protected]1c35a482011-10-25 23:19:5172 // Returns true if this callback equals |other|. |other| may be null.
73 bool Equals(const CallbackBase& other) const;
74
[email protected]59eff912011-02-18 23:29:3175 CallbackBase(InvokeFuncStorage polymorphic_invoke,
76 scoped_refptr<InvokerStorageBase>* invoker_storage);
77
[email protected]1c35a482011-10-25 23:19:5178 // Force the destructor to be instantiated inside this translation unit so
[email protected]59eff912011-02-18 23:29:3179 // that our subclasses will not get inlined versions. Avoids more template
80 // bloat.
81 ~CallbackBase();
82
83 scoped_refptr<InvokerStorageBase> invoker_storage_;
84 InvokeFuncStorage polymorphic_invoke_;
85};
86
[email protected]c18b1052011-03-24 02:02:1787// This is a typetraits object that's used to take an argument type, and
88// extract a suitable type for storing and forwarding arguments.
89//
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.
93//
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.
98template <typename T>
99struct ParamTraits {
100 typedef const T& ForwardType;
101 typedef T StorageType;
102};
103
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.
107//
108// The ForwardType should only be used for unbound arguments.
109template <typename T>
110struct ParamTraits<T&> {
111 typedef T& ForwardType;
112 typedef T StorageType;
113};
114
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
119// restriction.
120template <typename T, size_t n>
121struct ParamTraits<T[n]> {
122 typedef const T* ForwardType;
123 typedef const T* StorageType;
124};
125
126// See comment for ParamTraits<T[n]>.
127template <typename T>
128struct ParamTraits<T[]> {
129 typedef const T* ForwardType;
130 typedef const T* StorageType;
131};
132
[email protected]b38d3572011-02-15 01:27:38133} // namespace internal
134} // namespace base
135
[email protected]59eff912011-02-18 23:29:31136#endif // BASE_CALLBACK_INTERNAL_H_