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