Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: base/callback.h

Issue 6109007: Unified callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: forgot to add bind.h Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // This file was GENERATED by command:
2 // pump.py callback.h.pump
3 // DO NOT EDIT BY HAND!!!
4
5
6 // 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 7 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 8 // found in the LICENSE file.
4 9
5 #ifndef BASE_CALLBACK_H_ 10 #ifndef BASE_CALLBACK_H_
6 #define BASE_CALLBACK_H_ 11 #define BASE_CALLBACK_H_
7 #pragma once 12 #pragma once
8 13
9 #include "base/tuple.h" 14 #include "base/callback_helpers.h"
10 #include "base/raw_scoped_refptr_mismatch_checker.h" 15 #include "base/callback_old.h"
11 16
12 // Callback -------------------------------------------------------------------- 17 // New, super-duper, unified Callback system. This will eventually replace
13 // 18 // NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
14 // A Callback is like a Task but with unbound parameters. It is basically an 19 // systems currently in the Chromium code base.
15 // object-oriented function pointer. 20 //
16 // 21 // WHAT IS THIS:
17 // Callbacks are designed to work with Tuples. A set of helper functions and 22 //
18 // classes is provided to hide the Tuple details from the consumer. Client 23 // The templated Callback class is a generalized funciton object. Together
19 // code will generally work with the CallbackRunner base class, which merely 24 // with the Bind() function in bind.h, they provide a type-safe method for
20 // provides a Run method and is returned by the New* functions. This allows 25 // performing currying of arguments, and createing a "closure."
21 // users to not care which type of class implements the callback, only that it 26 //
22 // has a certain number and type of arguments. 27 // In programing languages, a closure is a first-class function where all its
23 // 28 // parameters have been bound (usually via currying). Closures are well
24 // The implementation of this is done by CallbackImpl, which inherits 29 // suited for representing, and passing around a unit of delayed execution.
25 // CallbackStorage to store the data. This allows the storage of the data 30 // They are used in Chromium code to schedule tasks on different MessageLoops.
26 // (requiring the class type T) to be hidden from users, who will want to call 31 //
27 // this regardless of the implementor's type T. 32 // EXAMPLE USAGE:
28 // 33 //
29 // Note that callbacks currently have no facility for cancelling or abandoning 34 // /* Binding a normal function. */
30 // them. We currently handle this at a higher level for cases where this is 35 // int Return5() { return 5; }
31 // necessary. The pointer in a callback must remain valid until the callback 36 // base::Callback<int(int)> func_cb = base::Bind(&Return5);
32 // is made. 37 // LOG(INFO) << func_cb.Run(5); // Prints 5.
33 // 38 //
34 // Like Task, the callback executor is responsible for deleting the callback 39 // void PrintHi() { LOG(INFO) << "hi."; }
35 // pointer once the callback has executed. 40 // base::Closure void_func_cb = base::Bind(&PrintHi);
36 // 41 // LOG(INFO) << void_func_cb.Run(); // Prints: hi.
37 // Example client usage: 42 //
38 // void Object::DoStuff(int, string); 43 // /* Binding a class method. */
39 // Callback2<int, string>::Type* callback = 44 // class Ref : public RefCountedThreadSafe<Ref> {
40 // NewCallback(obj, &Object::DoStuff); 45 // public:
41 // callback->Run(5, string("hello")); 46 // int Foo() { return 3; }
42 // delete callback; 47 // void PrintBye() { LOG(INFO) << "bye."; }
43 // or, equivalently, using tuples directly: 48 // };
44 // CallbackRunner<Tuple2<int, string> >* callback = 49 // scoped_refptr<Ref> ref = new Ref();
45 // NewCallback(obj, &Object::DoStuff); 50 // base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
46 // callback->RunWithParams(MakeTuple(5, string("hello"))); 51 // LOG(INFO) << ref_cb.Run(); // Prints out 3.
47 // 52 //
48 // There is also a 0-args version that returns a value. Example: 53 // base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
49 // int Object::GetNextInt(); 54 // void_ref_cb.Run(); // Prints: bye.
50 // CallbackWithReturnValue<int>::Type* callback = 55 //
51 // NewCallbackWithReturnValue(obj, &Object::GetNextInt); 56 // /* Binding a class method in a non-refcounted class.
52 // int next_int = callback->Run(); 57 // *
53 // delete callback; 58 // * WARNING: You must be sure the referee outlives the callback!
54 59 // * This is particularly important if you post a closure to a
55 // Base for all Callbacks that handles storage of the pointers. 60 // * MessageLoop because then it becomes hard to know what the
56 template <class T, typename Method> 61 // * lifetime of the referee needs to be.
57 class CallbackStorage { 62 // */
58 public: 63 // class NoRef {
59 CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) { 64 // public:
60 } 65 // int Foo() { return 4; }
61 66 // void PrintWhy() { LOG(INFO) << "why???"; }
62 protected: 67 // };
63 T* obj_; 68 // NoRef no_ref;
64 Method meth_; 69 // base::Callback<int(void)> base::no_ref_cb =
65 }; 70 // base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
66 71 // LOG(INFO) << ref_cb.Run(); // Prints out 4.
67 // Interface that is exposed to the consumer, that does the actual calling 72 //
68 // of the method. 73 // base::Closure void_no_ref_cb =
69 template <typename Params> 74 // base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
70 class CallbackRunner { 75 // void_no_ref_cb.Run(); // Prints: why???
71 public: 76 //
72 typedef Params TupleType; 77 // /* Binding a reference. */
73 78 // int Identity(int n) { return n; }
74 virtual ~CallbackRunner() {} 79 // int value = 1;
75 virtual void RunWithParams(const Params& params) = 0; 80 // base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
76 81 // base::Callback<int(void)> bound_ref_cb =
77 // Convenience functions so callers don't have to deal with Tuples. 82 // base::Bind(&Identity, base::ConstRef(value));
78 inline void Run() { 83 // LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
79 RunWithParams(Tuple0()); 84 // LOG(INFO) << bound_ref_cb.Run(); // Prints 1.
80 } 85 // value = 2;
81 86 // LOG(INFO) << bound_copy_cb.Run(); // Prints 1.
82 template <typename Arg1> 87 // LOG(INFO) << bound_ref_cb.Run(); // Prints 2.
83 inline void Run(const Arg1& a) { 88 //
84 RunWithParams(Params(a)); 89 //
85 } 90 // WHERE IS THIS DESIGN FROM:
86 91 //
87 template <typename Arg1, typename Arg2> 92 // The design Callback and Bind is heavily influenced by C++'s
88 inline void Run(const Arg1& a, const Arg2& b) { 93 // tr1::function/tr1::bind, and by the "Google Callback" system used inside
89 RunWithParams(Params(a, b)); 94 // Google.
90 } 95 //
91 96 //
92 template <typename Arg1, typename Arg2, typename Arg3> 97 // HOW THE IMPLEMENTATION WORKS:
93 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) { 98 //
94 RunWithParams(Params(a, b, c)); 99 // There are three main components to the system:
95 } 100 // 1) The Callback classes.
96 101 // 2) The Bind() functions.
97 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> 102 // 3) The arguments wrappers (eg., Unretained() and ConstRef()).
98 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) { 103 //
99 RunWithParams(Params(a, b, c, d)); 104 // The Callback classes represent a generic function pointer. Internally,
100 } 105 // it stores a refcounted piece of state that represents the target function
101 106 // and all its bound parameters. Each Callback specialization has a templated
102 template <typename Arg1, typename Arg2, typename Arg3, 107 // constructor that takes an InvokerStorageHolder<> object. In the context of
103 typename Arg4, typename Arg5> 108 // the constructor, the static type of this InvokerStorageHolder<> object
104 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, 109 // uniquely identifies the function it is representing, all its bound
105 const Arg4& d, const Arg5& e) { 110 // parameters, and a DoInvoke that is capable of invoking the target.
106 RunWithParams(Params(a, b, c, d, e)); 111 //
107 } 112 // Callback's constructor is takes the InvokerStorageHolder<> that has the
108 }; 113 // full static type and erases the target function type, and the bound
109 114 // parameters. It does this by storing a pointer to the specific DoInvoke
110 template <class T, typename Method, typename Params> 115 // function, and upcasting the state of InvokerStorageHolder<> to a
111 class CallbackImpl : public CallbackStorage<T, Method>, 116 // InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
112 public CallbackRunner<Params> { 117 // is only used with the stored DoInvoke pointer.
113 public: 118 //
114 CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) { 119 // To create InvokerStorageHolder<> objects, we use the Bind() functions.
115 } 120 // These functions, along with a set of internal templates, are reponsible for
116 virtual void RunWithParams(const Params& params) { 121 //
117 // use "this->" to force C++ to look inside our templatized base class; see 122 // - Unwrapping the function signature into return type, and parameters
118 // Effective C++, 3rd Ed, item 43, p210 for details. 123 // - Determining the number of parameters that are bound
119 DispatchToMethod(this->obj_, this->meth_, params); 124 // - Creating the storage for the bound parameters
120 } 125 // - Performing compile-time asserts to avoid error-prone behavior
121 }; 126 // - Returning an InvokerStorageHolder<> with an DoInvoke that has an arity
122 127 // matching the number of unbound parameters, and knows the correct
123 // 0-arg implementation 128 // refcounting semantics for the target object if we are binding a class
124 struct Callback0 { 129 // method.
125 typedef CallbackRunner<Tuple0> Type; 130 //
126 }; 131 // The Bind functions do the above using type-inference, and template
127 132 // specializations.
128 template <class T> 133 //
129 typename Callback0::Type* NewCallback(T* object, void (T::*method)()) { 134 // By default Bind() will store copies of all bound parameters, and attempt
130 return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method); 135 // to refcount a target object if the function being bound is a class method.
131 } 136 //
132 137 // To change this behavior, we introduce a set of argument wrappers
133 // 1-arg implementation 138 // (eg. Unretained(), and ConstRef()). These are simple container templates
134 template <typename Arg1> 139 // that are passed by value, and wrap a pointer to argument.
135 struct Callback1 { 140 //
136 typedef CallbackRunner<Tuple1<Arg1> > Type; 141 // ConstRef() allows Bind()'s storage to preserve copy-semantics even if we
137 }; 142 // wish to pass the invoked object a reference to the bound parameter.
brettw 2011/02/10 17:41:24 These two paragraphs about ConstRef and Unretained
awong 2011/02/12 09:44:45 Done.
138 143 //
139 template <class T, typename Arg1> 144 // Unretained() allows us to tag an object for different refcounting semantics.
140 typename Callback1<Arg1>::Type* NewCallback(T* object, 145 //
141 void (T::*method)(Arg1)) { 146 // These types are passed to the Unwrap() functions, and the MaybeRefcount()
142 return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method); 147 // functions respectively to modify the behavior of Bind(). The Unwrap()
143 } 148 // and MaybeRefcount() functions change behavior by doing partial
144 149 // specialization based on whether or not a parameter is a wrapper type.
145 // 2-arg implementation 150 //
146 template <typename Arg1, typename Arg2> 151 // ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium.
147 struct Callback2 { 152 //
148 typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type; 153 //
149 }; 154 // WHY NOT TR1 FUNCTION/BIND?
150 155 //
151 template <class T, typename Arg1, typename Arg2> 156 // Direct use of tr1::function and tr1::bind was considered, but ultimately
152 typename Callback2<Arg1, Arg2>::Type* NewCallback( 157 // rejected because of the number of copy constructors invocations involved
153 T* object, 158 // in the binding of arguments during construction, and the forwarding of
154 void (T::*method)(Arg1, Arg2)) { 159 // arguments during invocation. These copies will no longer be an issue in
155 return new CallbackImpl<T, void (T::*)(Arg1, Arg2), 160 // C++0x because C++0x will support rvalue reference allowing for the compiler
156 Tuple2<Arg1, Arg2> >(object, method); 161 // to avoid these copies. However, waiting for C++0x is not an option.
157 } 162 //
158 163 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
159 // 3-arg implementation 164 // tr1::bind call itself will invoke a non-trivial copy constructor three times
160 template <typename Arg1, typename Arg2, typename Arg3> 165 // for each bound parameter. Also, each when passing a tr1::function, each
161 struct Callback3 { 166 // bound argument will be copied again.
162 typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type; 167 //
163 }; 168 // In addition to the copies taken at binding and invocation, copying a
164 169 // tr1::function causes a copy to be made of all the bound parameters and
165 template <class T, typename Arg1, typename Arg2, typename Arg3> 170 // state.
166 typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( 171 //
167 T* object, 172 // Furthermore, in Chromium, it is desirable for the Callback to take a
168 void (T::*method)(Arg1, Arg2, Arg3)) { 173 // reference on a target object when representing a class method call. This
169 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3), 174 // is not supported by tr1.
170 Tuple3<Arg1, Arg2, Arg3> >(object, method); 175 //
171 } 176 // Lastly, tr1::function and tr1::bind has a more general and flexible API.
172 177 // This includes things like argument reordering by use of
173 // 4-arg implementation 178 // tr1::bind::placeholder, support for non-const reference parameters, and some
174 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> 179 // limited amount of subtyping of the tr1::function object (eg.,
175 struct Callback4 { 180 // tr1::function<int(int)> is convertable to tr1::function<void(int)>).
176 typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type; 181 //
177 }; 182 // These are not features that are required in Chromium. Some of them, such as
178 183 // allowing for reference parameters, and subtyping of functions, may actually
179 template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> 184 // because a source of errors. Removing support for these features actually
180 typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( 185 // allows for a simpler implementation, and a terser Currying API.
181 T* object, 186 //
182 void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { 187 //
183 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4), 188 // WHY NOT GOOGLE CALLBACKS?
184 Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method); 189 //
185 } 190 // The Google callback system also does not support refcounting. Furthermore,
186 191 // its implementation has a number of strange edge cases with respect to type
187 // 5-arg implementation 192 // convesrion of its arguments. In particular, the argument's constness must
188 template <typename Arg1, typename Arg2, typename Arg3, 193 // at times match exactly the function signature, or the type-inference might
189 typename Arg4, typename Arg5> 194 // break. Given the above, writing a custom solution was easier.
190 struct Callback5 { 195 //
191 typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type; 196 //
192 }; 197 // MISSING FUNCTIONALITY
193 198 // - Invoking the return of Bind. Bind(&foo).Run() does not work;
194 template <class T, typename Arg1, typename Arg2, 199 // - Binding arrays to functions that take a non-const pointer.
195 typename Arg3, typename Arg4, typename Arg5> 200 // Example:
196 typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( 201 // void Foo(const char* ptr);
197 T* object, 202 // void Bar(char* ptr);
198 void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { 203 // Bind(&Foo, "test");
199 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), 204 // Bind(&Bar, "tesT"); // This fails because ptr is not const.
200 Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method); 205
201 } 206 namespace base {
202 207
203 // An UnboundMethod is a wrapper for a method where the actual object is 208 // First, we forward declare the Callback class template. This informs the
204 // provided at Run dispatch time. 209 // compiler that the template only has 1 type parameter which is the function
205 template <class T, class Method, class Params> 210 // signature that the Callback is representing.
206 class UnboundMethod { 211 //
207 public: 212 // After this, create template specializations for 0-6 parameters. Note that
208 UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { 213 // even though the template typelist grows, the specialization still
209 COMPILE_ASSERT( 214 // only has one type: the function signature.
210 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 215 //
211 badunboundmethodparams); 216 // Also, note that the templated constructor should *not* be explicit. This is
212 } 217 // to allow for a natural assignment syntax from the result of Bind(), which
213 void Run(T* obj) const { 218 // is not the same type as Callback(). See the description of Bind for
214 DispatchToMethod(obj, m_, p_); 219 // details.
215 } 220 template <typename Sig>
216 private: 221 class Callback;
217 Method m_; 222
218 Params p_; 223 template <typename R>
219 }; 224 class Callback<R(void)> {
220 225 public:
221 // Return value implementation with no args. 226 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*);
222 template <typename ReturnValue> 227
223 struct CallbackWithReturnValue { 228 Callback() : polymorphic_invoke_(NULL) { }
224 class Type { 229
225 public: 230 // We pass InvokerStorageHolder by const ref to avoid incurring an
226 virtual ~Type() {} 231 // unnecssary AddRef/Unref pair even though we will modify the object.
227 virtual ReturnValue Run() = 0; 232 // We cannot use a normal reference because the compiler will warn
228 }; 233 // since this is often used on a return value, which is a temporary.
229 }; 234 template <typename T>
230 235 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
231 template <class T, typename Method, typename ReturnValue> 236 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
232 class CallbackWithReturnValueImpl 237 invoker_storage_.swap(invoker_holder.invoker_storage_);
233 : public CallbackStorage<T, Method>, 238 }
234 public CallbackWithReturnValue<ReturnValue>::Type { 239
235 public: 240 R Run(void) const {
236 CallbackWithReturnValueImpl(T* obj, Method meth) 241 return polymorphic_invoke_(invoker_storage_.get());
237 : CallbackStorage<T, Method>(obj, meth) {} 242 }
238 243
239 virtual ReturnValue Run() { 244 private:
240 return (this->obj_->*(this->meth_))(); 245 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
241 } 246 PolymorphicInvoke polymorphic_invoke_;
242 247 };
243 protected: 248
244 virtual ~CallbackWithReturnValueImpl() {} 249 template <typename R, typename A1>
245 }; 250 class Callback<R(A1)> {
246 251 public:
247 template <class T, typename ReturnValue> 252 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&);
248 typename CallbackWithReturnValue<ReturnValue>::Type* 253
249 NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) { 254 Callback() : polymorphic_invoke_(NULL) { }
250 return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>( 255
251 object, method); 256 // We pass InvokerStorageHolder by const ref to avoid incurring an
252 } 257 // unnecssary AddRef/Unref pair even though we will modify the object.
258 // We cannot use a normal reference because the compiler will warn
259 // since this is often used on a return value, which is a temporary.
260 template <typename T>
261 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
262 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
263 invoker_storage_.swap(invoker_holder.invoker_storage_);
264 }
265
266 R Run(const A1& a1) const {
267 return polymorphic_invoke_(invoker_storage_.get(), a1);
268 }
269
270 private:
271 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
272 PolymorphicInvoke polymorphic_invoke_;
273 };
274
275 template <typename R, typename A1, typename A2>
276 class Callback<R(A1, A2)> {
277 public:
278 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
279 const A2&);
280
281 Callback() : polymorphic_invoke_(NULL) { }
282
283 // We pass InvokerStorageHolder by const ref to avoid incurring an
284 // unnecssary AddRef/Unref pair even though we will modify the object.
285 // We cannot use a normal reference because the compiler will warn
286 // since this is often used on a return value, which is a temporary.
287 template <typename T>
288 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
289 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
290 invoker_storage_.swap(invoker_holder.invoker_storage_);
291 }
292
293 R Run(const A1& a1,
294 const A2& a2) const {
295 return polymorphic_invoke_(invoker_storage_.get(), a1,
296 a2);
297 }
298
299 private:
300 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
301 PolymorphicInvoke polymorphic_invoke_;
302 };
303
304 template <typename R, typename A1, typename A2, typename A3>
305 class Callback<R(A1, A2, A3)> {
306 public:
307 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
308 const A2&,
309 const A3&);
310
311 Callback() : polymorphic_invoke_(NULL) { }
312
313 // We pass InvokerStorageHolder by const ref to avoid incurring an
314 // unnecssary AddRef/Unref pair even though we will modify the object.
315 // We cannot use a normal reference because the compiler will warn
316 // since this is often used on a return value, which is a temporary.
317 template <typename T>
318 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
319 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
320 invoker_storage_.swap(invoker_holder.invoker_storage_);
321 }
322
323 R Run(const A1& a1,
324 const A2& a2,
325 const A3& a3) const {
326 return polymorphic_invoke_(invoker_storage_.get(), a1,
327 a2,
328 a3);
329 }
330
331 private:
332 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
333 PolymorphicInvoke polymorphic_invoke_;
334 };
335
336 template <typename R, typename A1, typename A2, typename A3, typename A4>
337 class Callback<R(A1, A2, A3, A4)> {
338 public:
339 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
340 const A2&,
341 const A3&,
342 const A4&);
343
344 Callback() : polymorphic_invoke_(NULL) { }
345
346 // We pass InvokerStorageHolder by const ref to avoid incurring an
347 // unnecssary AddRef/Unref pair even though we will modify the object.
348 // We cannot use a normal reference because the compiler will warn
349 // since this is often used on a return value, which is a temporary.
350 template <typename T>
351 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
352 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
353 invoker_storage_.swap(invoker_holder.invoker_storage_);
354 }
355
356 R Run(const A1& a1,
357 const A2& a2,
358 const A3& a3,
359 const A4& a4) const {
360 return polymorphic_invoke_(invoker_storage_.get(), a1,
361 a2,
362 a3,
363 a4);
364 }
365
366 private:
367 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
368 PolymorphicInvoke polymorphic_invoke_;
369 };
370
371 template <typename R, typename A1, typename A2, typename A3, typename A4,
372 typename A5>
373 class Callback<R(A1, A2, A3, A4, A5)> {
374 public:
375 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
376 const A2&,
377 const A3&,
378 const A4&,
379 const A5&);
380
381 Callback() : polymorphic_invoke_(NULL) { }
382
383 // We pass InvokerStorageHolder by const ref to avoid incurring an
384 // unnecssary AddRef/Unref pair even though we will modify the object.
385 // We cannot use a normal reference because the compiler will warn
386 // since this is often used on a return value, which is a temporary.
387 template <typename T>
388 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
389 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
390 invoker_storage_.swap(invoker_holder.invoker_storage_);
391 }
392
393 R Run(const A1& a1,
394 const A2& a2,
395 const A3& a3,
396 const A4& a4,
397 const A5& a5) const {
398 return polymorphic_invoke_(invoker_storage_.get(), a1,
399 a2,
400 a3,
401 a4,
402 a5);
403 }
404
405 private:
406 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
407 PolymorphicInvoke polymorphic_invoke_;
408 };
409
410 template <typename R, typename A1, typename A2, typename A3, typename A4,
411 typename A5, typename A6>
412 class Callback<R(A1, A2, A3, A4, A5, A6)> {
413 public:
414 typedef R(*PolymorphicInvoke)(internal::InvokerStorageBase*, const A1&,
415 const A2&,
416 const A3&,
417 const A4&,
418 const A5&,
419 const A6&);
420
421 Callback() : polymorphic_invoke_(NULL) { }
422
423 // We pass InvokerStorageHolder by const ref to avoid incurring an
424 // unnecssary AddRef/Unref pair even though we will modify the object.
425 // We cannot use a normal reference because the compiler will warn
426 // since this is often used on a return value, which is a temporary.
427 template <typename T>
428 Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
429 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
430 invoker_storage_.swap(invoker_holder.invoker_storage_);
431 }
432
433 R Run(const A1& a1,
434 const A2& a2,
435 const A3& a3,
436 const A4& a4,
437 const A5& a5,
438 const A6& a6) const {
439 return polymorphic_invoke_(invoker_storage_.get(), a1,
440 a2,
441 a3,
442 a4,
443 a5,
444 a6);
445 }
446
447 private:
448 scoped_refptr<internal::InvokerStorageBase> invoker_storage_;
449 PolymorphicInvoke polymorphic_invoke_;
450 };
451
452
453 // Syntactic sugar to make Callbacks<void(void)> easier to declare since it
454 // will be used in a lot of APIs with delayed execution.
455 typedef Callback<void(void)> Closure;
456
457 } // namespace base
253 458
254 #endif // BASE_CALLBACK_H 459 #endif // BASE_CALLBACK_H
OLDNEW
« base/bind_helpers.h ('K') | « base/bind_unittest.cc ('k') | base/callback.h.pump » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698