|
1 // Copyright (c) 2006-2008 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 #ifndef BASE_TASK_H_ |
|
6 #define BASE_TASK_H_ |
|
7 |
|
8 #include "base/non_thread_safe.h" |
|
9 #include "base/revocable_store.h" |
|
10 #include "base/tracked.h" |
|
11 #include "base/tuple.h" |
|
12 |
|
13 // Task ------------------------------------------------------------------------ |
|
14 // |
|
15 // A task is a generic runnable thingy, usually used for running code on a |
|
16 // different thread or for scheduling future tasks off of the message loop. |
|
17 |
|
18 class Task : public tracked_objects::Tracked { |
|
19 public: |
|
20 Task() {} |
|
21 virtual ~Task() {} |
|
22 |
|
23 // Tasks are automatically deleted after Run is called. |
|
24 virtual void Run() = 0; |
|
25 }; |
|
26 |
|
27 class CancelableTask : public Task { |
|
28 public: |
|
29 // Not all tasks support cancellation. |
|
30 virtual void Cancel() = 0; |
|
31 }; |
|
32 |
|
33 // Scoped Factories ------------------------------------------------------------ |
|
34 // |
|
35 // These scoped factory objects can be used by non-refcounted objects to safely |
|
36 // place tasks in a message loop. Each factory guarantees that the tasks it |
|
37 // produces will not run after the factory is destroyed. Commonly, factories |
|
38 // are declared as class members, so the class' tasks will automatically cancel |
|
39 // when the class instance is destroyed. |
|
40 // |
|
41 // Exampe Usage: |
|
42 // |
|
43 // class MyClass { |
|
44 // private: |
|
45 // // This factory will be used to schedule invocations of SomeMethod. |
|
46 // ScopedRunnableMethodFactory<MyClass> some_method_factory_; |
|
47 // |
|
48 // public: |
|
49 // // It is safe to suppress warning 4355 here. |
|
50 // MyClass() : some_method_factory_(this) { } |
|
51 // |
|
52 // void SomeMethod() { |
|
53 // // If this function might be called directly, you might want to revoke |
|
54 // // any outstanding runnable methods scheduled to call it. If it's not |
|
55 // // referenced other than by the factory, this is unnecessary. |
|
56 // some_method_factory_.RevokeAll(); |
|
57 // ... |
|
58 // } |
|
59 // |
|
60 // void ScheduleSomeMethod() { |
|
61 // // If you'd like to only only have one pending task at a time, test for |
|
62 // // |empty| before manufacturing another task. |
|
63 // if (!some_method_factory_.empty()) |
|
64 // return; |
|
65 // |
|
66 // // The factories are not thread safe, so always invoke on |
|
67 // // |MessageLoop::current()|. |
|
68 // MessageLoop::current()->PostDelayedTask(FROM_HERE, |
|
69 // some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod), |
|
70 // kSomeMethodDelayMS); |
|
71 // } |
|
72 // }; |
|
73 |
|
74 // A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from |
|
75 // running after it is destroyed. |
|
76 template<class TaskType> |
|
77 class ScopedTaskFactory : public RevocableStore { |
|
78 public: |
|
79 ScopedTaskFactory() { } |
|
80 |
|
81 // Create a new task. |
|
82 inline TaskType* NewTask() { |
|
83 return new TaskWrapper(this); |
|
84 } |
|
85 |
|
86 class TaskWrapper : public TaskType, public NonThreadSafe { |
|
87 public: |
|
88 explicit TaskWrapper(RevocableStore* store) : revocable_(store) { } |
|
89 |
|
90 virtual void Run() { |
|
91 if (!revocable_.revoked()) |
|
92 TaskType::Run(); |
|
93 } |
|
94 |
|
95 private: |
|
96 Revocable revocable_; |
|
97 |
|
98 DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper); |
|
99 }; |
|
100 |
|
101 private: |
|
102 DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory); |
|
103 }; |
|
104 |
|
105 // A ScopedRunnableMethodFactory creates runnable methods for a specified |
|
106 // object. This is particularly useful for generating callbacks for |
|
107 // non-reference counted objects when the factory is a member of the object. |
|
108 template<class T> |
|
109 class ScopedRunnableMethodFactory : public RevocableStore { |
|
110 public: |
|
111 explicit ScopedRunnableMethodFactory(T* object) : object_(object) { } |
|
112 |
|
113 template <class Method> |
|
114 inline Task* NewRunnableMethod(Method method) { |
|
115 typedef typename ScopedTaskFactory<RunnableMethod< |
|
116 Method, Tuple0> >::TaskWrapper TaskWrapper; |
|
117 |
|
118 TaskWrapper* task = new TaskWrapper(this); |
|
119 task->Init(object_, method, MakeTuple()); |
|
120 return task; |
|
121 } |
|
122 |
|
123 template <class Method, class A> |
|
124 inline Task* NewRunnableMethod(Method method, const A& a) { |
|
125 typedef typename ScopedTaskFactory<RunnableMethod< |
|
126 Method, Tuple1<A> > >::TaskWrapper TaskWrapper; |
|
127 |
|
128 TaskWrapper* task = new TaskWrapper(this); |
|
129 task->Init(object_, method, MakeTuple(a)); |
|
130 return task; |
|
131 } |
|
132 |
|
133 template <class Method, class A, class B> |
|
134 inline Task* NewRunnableMethod(Method method, const A& a, const B& b) { |
|
135 typedef typename ScopedTaskFactory<RunnableMethod< |
|
136 Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper; |
|
137 |
|
138 TaskWrapper* task = new TaskWrapper(this); |
|
139 task->Init(object_, method, MakeTuple(a, b)); |
|
140 return task; |
|
141 } |
|
142 |
|
143 template <class Method, class A, class B, class C> |
|
144 inline Task* NewRunnableMethod(Method method, |
|
145 const A& a, |
|
146 const B& b, |
|
147 const C& c) { |
|
148 typedef typename ScopedTaskFactory<RunnableMethod< |
|
149 Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper; |
|
150 |
|
151 TaskWrapper* task = new TaskWrapper(this); |
|
152 task->Init(object_, method, MakeTuple(a, b, c)); |
|
153 return task; |
|
154 } |
|
155 |
|
156 template <class Method, class A, class B, class C, class D> |
|
157 inline Task* NewRunnableMethod(Method method, |
|
158 const A& a, |
|
159 const B& b, |
|
160 const C& c, |
|
161 const D& d) { |
|
162 typedef typename ScopedTaskFactory<RunnableMethod< |
|
163 Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper; |
|
164 |
|
165 TaskWrapper* task = new TaskWrapper(this); |
|
166 task->Init(object_, method, MakeTuple(a, b, c, d)); |
|
167 return task; |
|
168 } |
|
169 |
|
170 template <class Method, class A, class B, class C, class D, class E> |
|
171 inline Task* NewRunnableMethod(Method method, |
|
172 const A& a, |
|
173 const B& b, |
|
174 const C& c, |
|
175 const D& d, |
|
176 const E& e) { |
|
177 typedef typename ScopedTaskFactory<RunnableMethod< |
|
178 Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper; |
|
179 |
|
180 TaskWrapper* task = new TaskWrapper(this); |
|
181 task->Init(object_, method, MakeTuple(a, b, c, d, e)); |
|
182 return task; |
|
183 } |
|
184 |
|
185 protected: |
|
186 template <class Method, class Params> |
|
187 class RunnableMethod : public Task { |
|
188 public: |
|
189 RunnableMethod() { } |
|
190 |
|
191 void Init(T* obj, Method meth, const Params& params) { |
|
192 obj_ = obj; |
|
193 meth_ = meth; |
|
194 params_ = params; |
|
195 } |
|
196 |
|
197 virtual void Run() { DispatchToMethod(obj_, meth_, params_); } |
|
198 |
|
199 private: |
|
200 T* obj_; |
|
201 Method meth_; |
|
202 Params params_; |
|
203 |
|
204 DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod); |
|
205 }; |
|
206 |
|
207 private: |
|
208 T* object_; |
|
209 |
|
210 DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory); |
|
211 }; |
|
212 |
|
213 // General task implementations ------------------------------------------------ |
|
214 |
|
215 // Task to delete an object |
|
216 template<class T> |
|
217 class DeleteTask : public CancelableTask { |
|
218 public: |
|
219 explicit DeleteTask(T* obj) : obj_(obj) { |
|
220 } |
|
221 virtual void Run() { |
|
222 delete obj_; |
|
223 } |
|
224 virtual void Cancel() { |
|
225 obj_ = NULL; |
|
226 } |
|
227 private: |
|
228 T* obj_; |
|
229 }; |
|
230 |
|
231 // Task to Release() an object |
|
232 template<class T> |
|
233 class ReleaseTask : public CancelableTask { |
|
234 public: |
|
235 explicit ReleaseTask(T* obj) : obj_(obj) { |
|
236 } |
|
237 virtual void Run() { |
|
238 if (obj_) |
|
239 obj_->Release(); |
|
240 } |
|
241 virtual void Cancel() { |
|
242 obj_ = NULL; |
|
243 } |
|
244 private: |
|
245 T* obj_; |
|
246 }; |
|
247 |
|
248 // RunnableMethodTraits -------------------------------------------------------- |
|
249 // |
|
250 // This traits-class is used by RunnableMethod to manage the lifetime of the |
|
251 // callee object. By default, it is assumed that the callee supports AddRef |
|
252 // and Release methods. A particular class can specialize this template to |
|
253 // define other lifetime management. For example, if the callee is known to |
|
254 // live longer than the RunnableMethod object, then a RunnableMethodTraits |
|
255 // struct could be defined with empty RetainCallee and ReleaseCallee methods. |
|
256 |
|
257 template <class T> |
|
258 struct RunnableMethodTraits { |
|
259 static void RetainCallee(T* obj) { |
|
260 obj->AddRef(); |
|
261 } |
|
262 static void ReleaseCallee(T* obj) { |
|
263 obj->Release(); |
|
264 } |
|
265 }; |
|
266 |
|
267 // RunnableMethod and RunnableFunction ----------------------------------------- |
|
268 // |
|
269 // Runnable methods are a type of task that call a function on an object when |
|
270 // they are run. We implement both an object and a set of NewRunnableMethod and |
|
271 // NewRunnableFunction functions for convenience. These functions are |
|
272 // overloaded and will infer the template types, simplifying calling code. |
|
273 // |
|
274 // The template definitions all use the following names: |
|
275 // T - the class type of the object you're supplying |
|
276 // this is not needed for the Static version of the call |
|
277 // Method/Function - the signature of a pointer to the method or function you |
|
278 // want to call |
|
279 // Param - the parameter(s) to the method, possibly packed as a Tuple |
|
280 // A - the first parameter (if any) to the method |
|
281 // B - the second parameter (if any) to the mathod |
|
282 // |
|
283 // Put these all together and you get an object that can call a method whose |
|
284 // signature is: |
|
285 // R T::MyFunction([A[, B]]) |
|
286 // |
|
287 // Usage: |
|
288 // PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]]) |
|
289 // PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]]) |
|
290 |
|
291 // RunnableMethod and NewRunnableMethod implementation ------------------------- |
|
292 |
|
293 template <class T, class Method, class Params> |
|
294 class RunnableMethod : public CancelableTask, |
|
295 public RunnableMethodTraits<T> { |
|
296 public: |
|
297 RunnableMethod(T* obj, Method meth, const Params& params) |
|
298 : obj_(obj), meth_(meth), params_(params) { |
|
299 this->RetainCallee(obj_); |
|
300 } |
|
301 ~RunnableMethod() { |
|
302 ReleaseCallee(); |
|
303 } |
|
304 |
|
305 virtual void Run() { |
|
306 if (obj_) |
|
307 DispatchToMethod(obj_, meth_, params_); |
|
308 } |
|
309 |
|
310 virtual void Cancel() { |
|
311 ReleaseCallee(); |
|
312 } |
|
313 |
|
314 private: |
|
315 void ReleaseCallee() { |
|
316 if (obj_) { |
|
317 RunnableMethodTraits<T>::ReleaseCallee(obj_); |
|
318 obj_ = NULL; |
|
319 } |
|
320 } |
|
321 |
|
322 T* obj_; |
|
323 Method meth_; |
|
324 Params params_; |
|
325 }; |
|
326 |
|
327 template <class T, class Method> |
|
328 inline CancelableTask* NewRunnableMethod(T* object, Method method) { |
|
329 return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); |
|
330 } |
|
331 |
|
332 template <class T, class Method, class A> |
|
333 inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) { |
|
334 return new RunnableMethod<T, Method, Tuple1<A> >(object, |
|
335 method, |
|
336 MakeTuple(a)); |
|
337 } |
|
338 |
|
339 template <class T, class Method, class A, class B> |
|
340 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
341 const A& a, const B& b) { |
|
342 return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, |
|
343 MakeTuple(a, b)); |
|
344 } |
|
345 |
|
346 template <class T, class Method, class A, class B, class C> |
|
347 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
348 const A& a, const B& b, const C& c) { |
|
349 return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method, |
|
350 MakeTuple(a, b, c)); |
|
351 } |
|
352 |
|
353 template <class T, class Method, class A, class B, class C, class D> |
|
354 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
355 const A& a, const B& b, |
|
356 const C& c, const D& d) { |
|
357 return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method, |
|
358 MakeTuple(a, b, |
|
359 c, d)); |
|
360 } |
|
361 |
|
362 template <class T, class Method, class A, class B, class C, class D, class E> |
|
363 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
364 const A& a, const B& b, |
|
365 const C& c, const D& d, const E& e) { |
|
366 return new RunnableMethod<T, |
|
367 Method, |
|
368 Tuple5<A, B, C, D, E> >(object, |
|
369 method, |
|
370 MakeTuple(a, b, c, d, e)); |
|
371 } |
|
372 |
|
373 template <class T, class Method, class A, class B, class C, class D, class E, |
|
374 class F> |
|
375 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
376 const A& a, const B& b, |
|
377 const C& c, const D& d, const E& e, |
|
378 const F& f) { |
|
379 return new RunnableMethod<T, |
|
380 Method, |
|
381 Tuple6<A, B, C, D, E, F> >(object, |
|
382 method, |
|
383 MakeTuple(a, b, c, d, e, |
|
384 f)); |
|
385 } |
|
386 |
|
387 template <class T, class Method, class A, class B, class C, class D, class E, |
|
388 class F, class G> |
|
389 inline CancelableTask* NewRunnableMethod(T* object, Method method, |
|
390 const A& a, const B& b, |
|
391 const C& c, const D& d, const E& e, |
|
392 const F& f, const G& g) { |
|
393 return new RunnableMethod<T, |
|
394 Method, |
|
395 Tuple7<A, B, C, D, E, F, G> >(object, |
|
396 method, |
|
397 MakeTuple(a, b, c, d, |
|
398 e, f, g)); |
|
399 } |
|
400 |
|
401 // RunnableFunction and NewRunnableFunction implementation --------------------- |
|
402 |
|
403 template <class Function, class Params> |
|
404 class RunnableFunction : public CancelableTask { |
|
405 public: |
|
406 RunnableFunction(Function function, const Params& params) |
|
407 : function_(function), params_(params) { |
|
408 } |
|
409 |
|
410 ~RunnableFunction() { |
|
411 } |
|
412 |
|
413 virtual void Run() { |
|
414 if (function_) |
|
415 DispatchToFunction(function_, params_); |
|
416 } |
|
417 |
|
418 virtual void Cancel() { |
|
419 function_ = NULL; |
|
420 } |
|
421 |
|
422 private: |
|
423 Function function_; |
|
424 Params params_; |
|
425 }; |
|
426 |
|
427 template <class Function> |
|
428 inline CancelableTask* NewRunnableFunction(Function function) { |
|
429 return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); |
|
430 } |
|
431 |
|
432 template <class Function, class A> |
|
433 inline CancelableTask* NewRunnableFunction(Function function, const A& a) { |
|
434 return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); |
|
435 } |
|
436 |
|
437 template <class Function, class A, class B> |
|
438 inline CancelableTask* NewRunnableFunction(Function function, |
|
439 const A& a, const B& b) { |
|
440 return new RunnableFunction<Function, Tuple2<A, B> >(function, |
|
441 MakeTuple(a, b)); |
|
442 } |
|
443 |
|
444 template <class Function, class A, class B, class C> |
|
445 inline CancelableTask* NewRunnableFunction(Function function, |
|
446 const A& a, const B& b, |
|
447 const C& c) { |
|
448 return new RunnableFunction<Function, Tuple3<A, B, C> >(function, |
|
449 MakeTuple(a, b, c)); |
|
450 } |
|
451 |
|
452 template <class Function, class A, class B, class C, class D> |
|
453 inline CancelableTask* NewRunnableFunction(Function function, |
|
454 const A& a, const B& b, |
|
455 const C& c, const D& d) { |
|
456 return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function, |
|
457 MakeTuple(a, b, |
|
458 c, d)); |
|
459 } |
|
460 |
|
461 template <class Function, class A, class B, class C, class D, class E> |
|
462 inline CancelableTask* NewRunnableFunction(Function function, |
|
463 const A& a, const B& b, |
|
464 const C& c, const D& d, |
|
465 const E& e) { |
|
466 return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function, |
|
467 MakeTuple(a, b, |
|
468 c, d, |
|
469 e)); |
|
470 } |
|
471 |
|
472 // Callback -------------------------------------------------------------------- |
|
473 // |
|
474 // A Callback is like a Task but with unbound parameters. It is basically an |
|
475 // object-oriented function pointer. |
|
476 // |
|
477 // Callbacks are designed to work with Tuples. A set of helper functions and |
|
478 // classes is provided to hide the Tuple details from the consumer. Client |
|
479 // code will generally work with the CallbackRunner base class, which merely |
|
480 // provides a Run method and is returned by the New* functions. This allows |
|
481 // users to not care which type of class implements the callback, only that it |
|
482 // has a certain number and type of arguments. |
|
483 // |
|
484 // The implementation of this is done by CallbackImpl, which inherits |
|
485 // CallbackStorage to store the data. This allows the storage of the data |
|
486 // (requiring the class type T) to be hidden from users, who will want to call |
|
487 // this regardless of the implementor's type T. |
|
488 // |
|
489 // Note that callbacks currently have no facility for cancelling or abandoning |
|
490 // them. We currently handle this at a higher level for cases where this is |
|
491 // necessary. The pointer in a callback must remain valid until the callback |
|
492 // is made. |
|
493 // |
|
494 // Like Task, the callback executor is responsible for deleting the callback |
|
495 // pointer once the callback has executed. |
|
496 // |
|
497 // Example client usage: |
|
498 // void Object::DoStuff(int, string); |
|
499 // Callback2<int, string>::Type* callback = |
|
500 // NewCallback(obj, &Object::DoStuff); |
|
501 // callback->Run(5, string("hello")); |
|
502 // delete callback; |
|
503 // or, equivalently, using tuples directly: |
|
504 // CallbackRunner<Tuple2<int, string> >* callback = |
|
505 // NewCallback(obj, &Object::DoStuff); |
|
506 // callback->RunWithParams(MakeTuple(5, string("hello"))); |
|
507 |
|
508 // Base for all Callbacks that handles storage of the pointers. |
|
509 template <class T, typename Method> |
|
510 class CallbackStorage { |
|
511 public: |
|
512 CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) { |
|
513 } |
|
514 |
|
515 protected: |
|
516 T* obj_; |
|
517 Method meth_; |
|
518 }; |
|
519 |
|
520 // Interface that is exposed to the consumer, that does the actual calling |
|
521 // of the method. |
|
522 template <typename Params> |
|
523 class CallbackRunner { |
|
524 public: |
|
525 typedef Params TupleType; |
|
526 |
|
527 virtual ~CallbackRunner() {} |
|
528 virtual void RunWithParams(const Params& params) = 0; |
|
529 |
|
530 // Convenience functions so callers don't have to deal with Tuples. |
|
531 inline void Run() { |
|
532 RunWithParams(Tuple0()); |
|
533 } |
|
534 |
|
535 template <typename Arg1> |
|
536 inline void Run(const Arg1& a) { |
|
537 RunWithParams(Params(a)); |
|
538 } |
|
539 |
|
540 template <typename Arg1, typename Arg2> |
|
541 inline void Run(const Arg1& a, const Arg2& b) { |
|
542 RunWithParams(Params(a, b)); |
|
543 } |
|
544 |
|
545 template <typename Arg1, typename Arg2, typename Arg3> |
|
546 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) { |
|
547 RunWithParams(Params(a, b, c)); |
|
548 } |
|
549 |
|
550 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> |
|
551 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) { |
|
552 RunWithParams(Params(a, b, c, d)); |
|
553 } |
|
554 |
|
555 template <typename Arg1, typename Arg2, typename Arg3, |
|
556 typename Arg4, typename Arg5> |
|
557 inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, |
|
558 const Arg4& d, const Arg5& e) { |
|
559 RunWithParams(Params(a, b, c, d, e)); |
|
560 } |
|
561 }; |
|
562 |
|
563 template <class T, typename Method, typename Params> |
|
564 class CallbackImpl : public CallbackStorage<T, Method>, |
|
565 public CallbackRunner<Params> { |
|
566 public: |
|
567 CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) { |
|
568 } |
|
569 virtual void RunWithParams(const Params& params) { |
|
570 // use "this->" to force C++ to look inside our templatized base class; see |
|
571 // Effective C++, 3rd Ed, item 43, p210 for details. |
|
572 DispatchToMethod(this->obj_, this->meth_, params); |
|
573 } |
|
574 }; |
|
575 |
|
576 // 0-arg implementation |
|
577 struct Callback0 { |
|
578 typedef CallbackRunner<Tuple0> Type; |
|
579 }; |
|
580 |
|
581 template <class T> |
|
582 typename Callback0::Type* NewCallback(T* object, void (T::*method)()) { |
|
583 return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method); |
|
584 } |
|
585 |
|
586 // 1-arg implementation |
|
587 template <typename Arg1> |
|
588 struct Callback1 { |
|
589 typedef CallbackRunner<Tuple1<Arg1> > Type; |
|
590 }; |
|
591 |
|
592 template <class T, typename Arg1> |
|
593 typename Callback1<Arg1>::Type* NewCallback(T* object, |
|
594 void (T::*method)(Arg1)) { |
|
595 return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method); |
|
596 } |
|
597 |
|
598 // 2-arg implementation |
|
599 template <typename Arg1, typename Arg2> |
|
600 struct Callback2 { |
|
601 typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type; |
|
602 }; |
|
603 |
|
604 template <class T, typename Arg1, typename Arg2> |
|
605 typename Callback2<Arg1, Arg2>::Type* NewCallback( |
|
606 T* object, |
|
607 void (T::*method)(Arg1, Arg2)) { |
|
608 return new CallbackImpl<T, void (T::*)(Arg1, Arg2), |
|
609 Tuple2<Arg1, Arg2> >(object, method); |
|
610 } |
|
611 |
|
612 // 3-arg implementation |
|
613 template <typename Arg1, typename Arg2, typename Arg3> |
|
614 struct Callback3 { |
|
615 typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type; |
|
616 }; |
|
617 |
|
618 template <class T, typename Arg1, typename Arg2, typename Arg3> |
|
619 typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( |
|
620 T* object, |
|
621 void (T::*method)(Arg1, Arg2, Arg3)) { |
|
622 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3), |
|
623 Tuple3<Arg1, Arg2, Arg3> >(object, method); |
|
624 } |
|
625 |
|
626 // 4-arg implementation |
|
627 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> |
|
628 struct Callback4 { |
|
629 typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type; |
|
630 }; |
|
631 |
|
632 template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> |
|
633 typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( |
|
634 T* object, |
|
635 void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { |
|
636 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4), |
|
637 Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method); |
|
638 } |
|
639 |
|
640 // 5-arg implementation |
|
641 template <typename Arg1, typename Arg2, typename Arg3, |
|
642 typename Arg4, typename Arg5> |
|
643 struct Callback5 { |
|
644 typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type; |
|
645 }; |
|
646 |
|
647 template <class T, typename Arg1, typename Arg2, |
|
648 typename Arg3, typename Arg4, typename Arg5> |
|
649 typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( |
|
650 T* object, |
|
651 void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { |
|
652 return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), |
|
653 Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method); |
|
654 } |
|
655 |
|
656 // An UnboundMethod is a wrapper for a method where the actual object is |
|
657 // provided at Run dispatch time. |
|
658 template <class T, class Method, class Params> |
|
659 class UnboundMethod { |
|
660 public: |
|
661 UnboundMethod(Method m, Params p) : m_(m), p_(p) {} |
|
662 void Run(T* obj) const { |
|
663 DispatchToMethod(obj, m_, p_); |
|
664 } |
|
665 private: |
|
666 Method m_; |
|
667 Params p_; |
|
668 }; |
|
669 |
|
670 #endif // BASE_TASK_H_ |