Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // This file was GENERATED by command: | |
| 2 // pump.py uber_callback.h.pump | |
| 3 // DO NOT EDIT BY HAND!!! | |
| 4 | |
| 5 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 6 // Use of this source code is governed by a BSD-style license that can be | |
| 7 // found in the LICENSE file. | |
| 8 | |
| 9 #ifndef BASE_UBER_CALLBACK_H_ | |
| 10 #define BASE_UBER_CALLBACK_H_ | |
| 11 #pragma once | |
| 12 | |
| 13 #include "base/ref_counted.h" | |
| 14 #include "base/raw_scoped_refptr_mismatch_checker.h" | |
| 15 | |
| 16 // New, super-duper, unified Callback system. This will eventually replace | |
| 17 // NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback | |
| 18 // systems currently in the Chromium code base. | |
| 19 // | |
| 20 // WHAT IS THIS: | |
| 21 // | |
| 22 // The templated Callback class is a generalized funciton object. Together | |
| 23 // with the Prebind() function, they provide a type-safe method for | |
| 24 // creating a "closure." In programing languages, a closure is a first-class | |
| 25 // function where all its parameters have been bound. Closures are well suited | |
| 26 // for passing around a unit of delayed execution. They are used in Chromium | |
| 27 // code to schedule tasks on different MessageLoops. | |
| 28 // | |
| 29 // EXAMPLE USAGE: | |
| 30 // | |
| 31 // TODO(ajwong): Add some good examples. | |
| 32 // | |
| 33 // | |
| 34 // WHERE IS THIS DESIGN FROM: | |
| 35 // | |
| 36 // The design Callback and Prebind is heavily influenced by C++'s | |
| 37 // tr1::function/tr1::bind, and by the "Google Callback" system used inside | |
| 38 // Google. | |
| 39 // | |
| 40 // | |
| 41 // WHY NOT TR1 FUNCTION/BIND? | |
| 42 // | |
| 43 // Direct use of tr1::function and tr1::bind was considered, but ultimately | |
| 44 // rejected because of the number of copy constructors invocations when binding | |
| 45 // arguments. These copies will no longer be an issue in C++0x; C++0x will | |
| 46 // support rvalue reference which will solve the copies. However, waiting for | |
| 47 // C++0x is not an option. | |
| 48 // | |
| 49 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the | |
| 50 // tr1::bind call itself will invoke a non-trivial copy constructor three times | |
| 51 // for each bound parameter. Also, each when passing a tr1::function, each | |
| 52 // bound argument will be copied again. | |
| 53 | |
| 54 namespace base { | |
| 55 | |
| 56 // InvokerStorageBase is used to provide an opaque handle that the Callback | |
| 57 // class can use to represent a function object with bound arguments. It | |
| 58 // behaves as an existential type that is used by a corresponding | |
| 59 // PolymorphicInvoke function to perform the function execution. This allows | |
| 60 // us to shield the Callback class from the types of the bound arguments via | |
| 61 // "type erasure." | |
| 62 // | |
| 63 // TODO(ajwong): Explain the PolymorphicInvoke setup is more understandable | |
| 64 // terms. | |
| 65 class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> { | |
| 66 protected: | |
| 67 friend class RefCountedThreadSafe<InvokerStorageBase>; | |
| 68 virtual ~InvokerStorageBase() {} | |
| 69 }; | |
| 70 | |
| 71 template <typename T> | |
| 72 struct InvokerStorageHolder { | |
| 73 explicit InvokerStorageHolder(T* invoker_storage) | |
| 74 : invoker_storage_(invoker_storage) { | |
| 75 } | |
| 76 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 77 }; | |
| 78 | |
| 79 template <typename T> | |
| 80 InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) { | |
| 81 return InvokerStorageHolder<T>(o); | |
| 82 } | |
| 83 | |
| 84 // First, forward declare the Callback class template. This informs the | |
| 85 // compiler that ther template only have 1 type parameter, the function | |
| 86 // signature that the Callback is abstracting. | |
| 87 // | |
| 88 // After this, create template specializations for 0-5 parameters. Note that | |
| 89 // even though the template typelist grows, that the specialization still | |
| 90 // only has one type: the function signature. | |
| 91 // | |
| 92 // Also, note that the templated constructor should *not* be explicit. This is | |
| 93 // to allow the natural assignment syntax from the result of Prebind(). | |
| 94 template <typename Sig> | |
| 95 class Callback; | |
| 96 template <typename R> | |
| 97 class Callback<R(void)> { | |
| 98 public: | |
| 99 typedef R(*PolymorphicInvoke)(InvokerStorageBase*); | |
| 100 | |
| 101 template <typename T> | |
| 102 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 103 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 104 invoker_storage_.swap( | |
| 105 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
|
akalin
2011/02/01 11:29:27
I don't like this const_cast, although I understan
awong
2011/02/01 23:20:45
I personally prefer the explicitness of the const_
| |
| 106 } | |
| 107 | |
| 108 R Run(void) { | |
| 109 return polymorphic_invoke_(invoker_storage_.get()); | |
| 110 } | |
| 111 | |
| 112 private: | |
| 113 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 114 PolymorphicInvoke polymorphic_invoke_; | |
| 115 }; | |
| 116 | |
| 117 template <typename R, typename A1> | |
| 118 class Callback<R(A1)> { | |
| 119 public: | |
| 120 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1); | |
| 121 | |
| 122 template <typename T> | |
| 123 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 124 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 125 invoker_storage_.swap( | |
| 126 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 127 } | |
| 128 | |
| 129 R Run(A1 a1) { | |
| 130 return polymorphic_invoke_(invoker_storage_.get(), a1); | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 135 PolymorphicInvoke polymorphic_invoke_; | |
| 136 }; | |
| 137 | |
| 138 template <typename R, typename A1, typename A2> | |
| 139 class Callback<R(A1, A2)> { | |
| 140 public: | |
| 141 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2); | |
| 142 | |
| 143 template <typename T> | |
| 144 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 145 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 146 invoker_storage_.swap( | |
| 147 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 148 } | |
| 149 | |
| 150 R Run(A1 a1, A2 a2) { | |
| 151 return polymorphic_invoke_(invoker_storage_.get(), a1, a2); | |
| 152 } | |
| 153 | |
| 154 private: | |
| 155 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 156 PolymorphicInvoke polymorphic_invoke_; | |
| 157 }; | |
| 158 | |
| 159 template <typename R, typename A1, typename A2, typename A3> | |
| 160 class Callback<R(A1, A2, A3)> { | |
| 161 public: | |
| 162 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3); | |
| 163 | |
| 164 template <typename T> | |
| 165 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 166 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 167 invoker_storage_.swap( | |
| 168 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 169 } | |
| 170 | |
| 171 R Run(A1 a1, A2 a2, A3 a3) { | |
| 172 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3); | |
| 173 } | |
| 174 | |
| 175 private: | |
| 176 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 177 PolymorphicInvoke polymorphic_invoke_; | |
| 178 }; | |
| 179 | |
| 180 template <typename R, typename A1, typename A2, typename A3, typename A4> | |
| 181 class Callback<R(A1, A2, A3, A4)> { | |
| 182 public: | |
| 183 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4); | |
| 184 | |
| 185 template <typename T> | |
| 186 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 187 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 188 invoker_storage_.swap( | |
| 189 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 190 } | |
| 191 | |
| 192 R Run(A1 a1, A2 a2, A3 a3, A4 a4) { | |
| 193 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4); | |
| 194 } | |
| 195 | |
| 196 private: | |
| 197 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 198 PolymorphicInvoke polymorphic_invoke_; | |
| 199 }; | |
| 200 | |
| 201 template <typename R, typename A1, typename A2, typename A3, typename A4, | |
| 202 typename A5> | |
| 203 class Callback<R(A1, A2, A3, A4, A5)> { | |
| 204 public: | |
| 205 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4, A5); | |
| 206 | |
| 207 template <typename T> | |
| 208 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 209 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 210 invoker_storage_.swap( | |
| 211 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 212 } | |
| 213 | |
| 214 R Run(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { | |
| 215 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5); | |
| 216 } | |
| 217 | |
| 218 private: | |
| 219 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 220 PolymorphicInvoke polymorphic_invoke_; | |
| 221 }; | |
| 222 | |
| 223 template <typename R, typename A1, typename A2, typename A3, typename A4, | |
| 224 typename A5, typename A6> | |
| 225 class Callback<R(A1, A2, A3, A4, A5, A6)> { | |
| 226 public: | |
| 227 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4, A5, A6); | |
| 228 | |
| 229 template <typename T> | |
| 230 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
| 231 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
| 232 invoker_storage_.swap( | |
| 233 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
| 234 } | |
| 235 | |
| 236 R Run(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { | |
| 237 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5, a6); | |
| 238 } | |
| 239 | |
| 240 private: | |
| 241 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
| 242 PolymorphicInvoke polymorphic_invoke_; | |
| 243 }; | |
| 244 | |
| 245 | |
| 246 // Syntactic sugar to make Callbacks<void(void)> easier to read since it will | |
| 247 // be used in a lot of APIs with delayed execution. | |
| 248 typedef Callback<void(void)> Closure; | |
| 249 | |
| 250 } // namespace base | |
| 251 | |
| 252 #endif // BASE_UBER_CALLBACK_H | |
| OLD | NEW |