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