• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //    * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //    * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //    * Neither the name of Google Inc. nor the name Chromium Embedded
14 // Framework nor the names of its contributors may be used to endorse
15 // or promote products derived from this software without specific prior
16 // written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // Do not include this header file directly. Use base/cef_bind.h or
31 // base/cef_callback.h instead.
32 
33 // This file contains utility functions and classes that help the
34 // implementation, and management of the Callback objects.
35 
36 #ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
37 #define CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
38 
39 #include <stddef.h>
40 
41 #include "include/base/cef_atomic_ref_count.h"
42 #include "include/base/cef_macros.h"
43 #include "include/base/cef_ref_counted.h"
44 #include "include/base/cef_scoped_ptr.h"
45 #include "include/base/cef_template_util.h"
46 
47 template <typename T>
48 class ScopedVector;
49 
50 namespace base {
51 namespace cef_internal {
52 class CallbackBase;
53 
54 // At the base level, the only task is to add reference counting data. Don't use
55 // RefCountedThreadSafe since it requires the destructor to be a virtual method.
56 // Creating a vtable for every BindState template instantiation results in a lot
57 // of bloat. Its only task is to call the destructor which can be done with a
58 // function pointer.
59 class BindStateBase {
60  protected:
BindStateBase(void (* destructor)(BindStateBase *))61   explicit BindStateBase(void (*destructor)(BindStateBase*))
62       : ref_count_(0), destructor_(destructor) {}
~BindStateBase()63   ~BindStateBase() {}
64 
65  private:
66   friend class scoped_refptr<BindStateBase>;
67   friend class CallbackBase;
68 
69   void AddRef();
70   void Release();
71 
72   AtomicRefCount ref_count_;
73 
74   // Pointer to a function that will properly destroy |this|.
75   void (*destructor_)(BindStateBase*);
76 
77   DISALLOW_COPY_AND_ASSIGN(BindStateBase);
78 };
79 
80 // Holds the Callback methods that don't require specialization to reduce
81 // template bloat.
82 class CallbackBase {
83  public:
84   // Returns true if Callback is null (doesn't refer to anything).
is_null()85   bool is_null() const { return bind_state_.get() == NULL; }
86 
87   // Returns the Callback into an uninitialized state.
88   void Reset();
89 
90  protected:
91   // In C++, it is safe to cast function pointers to function pointers of
92   // another type. It is not okay to use void*. We create a InvokeFuncStorage
93   // that that can store our function pointer, and then cast it back to
94   // the original type on usage.
95   typedef void (*InvokeFuncStorage)(void);
96 
97   // Returns true if this callback equals |other|. |other| may be null.
98   bool Equals(const CallbackBase& other) const;
99 
100   // Allow initializing of |bind_state_| via the constructor to avoid default
101   // initialization of the scoped_refptr.  We do not also initialize
102   // |polymorphic_invoke_| here because doing a normal assignment in the
103   // derived Callback templates makes for much nicer compiler errors.
104   explicit CallbackBase(BindStateBase* bind_state);
105 
106   // Force the destructor to be instantiated inside this translation unit so
107   // that our subclasses will not get inlined versions.  Avoids more template
108   // bloat.
109   ~CallbackBase();
110 
111   scoped_refptr<BindStateBase> bind_state_;
112   InvokeFuncStorage polymorphic_invoke_;
113 };
114 
115 // A helper template to determine if given type is non-const move-only-type,
116 // i.e. if a value of the given type should be passed via .Pass() in a
117 // destructive way.
118 template <typename T>
119 struct IsMoveOnlyType {
120   template <typename U>
121   static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
122 
123   template <typename U>
124   static NoType Test(...);
125 
126   static const bool value =
127       sizeof(Test<T>(0)) == sizeof(YesType) && !is_const<T>::value;
128 };
129 
130 // This is a typetraits object that's used to take an argument type, and
131 // extract a suitable type for storing and forwarding arguments.
132 //
133 // In particular, it strips off references, and converts arrays to
134 // pointers for storage; and it avoids accidentally trying to create a
135 // "reference of a reference" if the argument is a reference type.
136 //
137 // This array type becomes an issue for storage because we are passing bound
138 // parameters by const reference. In this case, we end up passing an actual
139 // array type in the initializer list which C++ does not allow.  This will
140 // break passing of C-string literals.
141 template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
142 struct CallbackParamTraits {
143   typedef const T& ForwardType;
144   typedef T StorageType;
145 };
146 
147 // The Storage should almost be impossible to trigger unless someone manually
148 // specifies type of the bind parameters.  However, in case they do,
149 // this will guard against us accidentally storing a reference parameter.
150 //
151 // The ForwardType should only be used for unbound arguments.
152 template <typename T>
153 struct CallbackParamTraits<T&, false> {
154   typedef T& ForwardType;
155   typedef T StorageType;
156 };
157 
158 // Note that for array types, we implicitly add a const in the conversion. This
159 // means that it is not possible to bind array arguments to functions that take
160 // a non-const pointer. Trying to specialize the template based on a "const
161 // T[n]" does not seem to match correctly, so we are stuck with this
162 // restriction.
163 template <typename T, size_t n>
164 struct CallbackParamTraits<T[n], false> {
165   typedef const T* ForwardType;
166   typedef const T* StorageType;
167 };
168 
169 // See comment for CallbackParamTraits<T[n]>.
170 template <typename T>
171 struct CallbackParamTraits<T[], false> {
172   typedef const T* ForwardType;
173   typedef const T* StorageType;
174 };
175 
176 // Parameter traits for movable-but-not-copyable scopers.
177 //
178 // Callback<>/Bind() understands movable-but-not-copyable semantics where
179 // the type cannot be copied but can still have its state destructively
180 // transferred (aka. moved) to another instance of the same type by calling a
181 // helper function.  When used with Bind(), this signifies transferal of the
182 // object's state to the target function.
183 //
184 // For these types, the ForwardType must not be a const reference, or a
185 // reference.  A const reference is inappropriate, and would break const
186 // correctness, because we are implementing a destructive move.  A non-const
187 // reference cannot be used with temporaries which means the result of a
188 // function or a cast would not be usable with Callback<> or Bind().
189 template <typename T>
190 struct CallbackParamTraits<T, true> {
191   typedef T ForwardType;
192   typedef T StorageType;
193 };
194 
195 // CallbackForward() is a very limited simulation of C++11's std::forward()
196 // used by the Callback/Bind system for a set of movable-but-not-copyable
197 // types.  It is needed because forwarding a movable-but-not-copyable
198 // argument to another function requires us to invoke the proper move
199 // operator to create a rvalue version of the type.  The supported types are
200 // whitelisted below as overloads of the CallbackForward() function. The
201 // default template compiles out to be a no-op.
202 //
203 // In C++11, std::forward would replace all uses of this function.  However, it
204 // is impossible to implement a general std::forward with C++11 due to a lack
205 // of rvalue references.
206 //
207 // In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
208 // simulate std::forward() and forward the result of one Callback as a
209 // parameter to another callback. This is to support Callbacks that return
210 // the movable-but-not-copyable types whitelisted above.
211 template <typename T>
212 typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) {
213   return t;
214 }
215 
216 template <typename T>
217 typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) {
218   return t.Pass();
219 }
220 
221 }  // namespace cef_internal
222 }  // namespace base
223 
224 #endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
225