• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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