task.h revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
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
19class Task : public tracked_objects::Tracked {
20 public:
21  Task() {}
22  virtual ~Task() {}
23
24  // Tasks are automatically deleted after Run is called.
25  virtual void Run() = 0;
26};
27
28class 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.
78template<class T>
79class ScopedRunnableMethodFactory {
80 public:
81  explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) {
82  }
83
84  template <class 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>
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>
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>
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>
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>
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
132  void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
133
134  bool empty() const { return !weak_factory_.HasWeakPtrs(); }
135
136 protected:
137  template <class Method, class Params>
138  class RunnableMethod : public Task {
139   public:
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
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
168template<class T>
169class DeleteTask : public CancelableTask {
170 public:
171  explicit DeleteTask(T* obj) : obj_(obj) {
172  }
173  virtual void Run() {
174    delete obj_;
175  }
176  virtual void Cancel() {
177    obj_ = NULL;
178  }
179 private:
180  T* obj_;
181};
182
183// Task to Release() an object
184template<class T>
185class ReleaseTask : public CancelableTask {
186 public:
187  explicit ReleaseTask(T* obj) : obj_(obj) {
188  }
189  virtual void Run() {
190    if (obj_)
191      obj_->Release();
192  }
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
209template <class T>
210struct RunnableMethodTraits {
211  RunnableMethodTraits() {
212#ifndef NDEBUG
213    origin_thread_id_ = PlatformThread::CurrentId();
214#endif
215  }
216
217  ~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
226  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
237  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
273template <class T, class Method, class Params>
274class RunnableMethod : public CancelableTask {
275 public:
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
283  ~RunnableMethod() {
284    ReleaseCallee();
285  }
286
287  virtual void Run() {
288    if (obj_)
289      DispatchToMethod(obj_, meth_, params_);
290  }
291
292  virtual void Cancel() {
293    ReleaseCallee();
294  }
295
296 private:
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
310template <class T, class Method>
311inline CancelableTask* NewRunnableMethod(T* object, Method method) {
312  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
313}
314
315template <class T, class Method, class A>
316inline 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
322template <class T, class Method, class A, class B>
323inline CancelableTask* NewRunnableMethod(T* object, Method method,
324const A& a, const B& b) {
325  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
326                                                      MakeTuple(a, b));
327}
328
329template <class T, class Method, class A, class B, class C>
330inline 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
336template <class T, class Method, class A, class B, class C, class D>
337inline 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
345template <class T, class Method, class A, class B, class C, class D, class E>
346inline 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
356template <class T, class Method, class A, class B, class C, class D, class E,
357          class F>
358inline 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
370template <class T, class Method, class A, class B, class C, class D, class E,
371          class F, class G>
372inline 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
386template <class Function, class Params>
387class RunnableFunction : public CancelableTask {
388 public:
389  RunnableFunction(Function function, const Params& params)
390      : function_(function), params_(params) {
391    COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value),
392                   badrunnablefunctionparams);
393  }
394
395  ~RunnableFunction() {
396  }
397
398  virtual void Run() {
399    if (function_)
400      DispatchToFunction(function_, params_);
401  }
402
403  virtual void Cancel() {
404  }
405
406 private:
407  Function function_;
408  Params params_;
409};
410
411template <class Function>
412inline CancelableTask* NewRunnableFunction(Function function) {
413  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
414}
415
416template <class Function, class A>
417inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
418  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
419}
420
421template <class Function, class A, class B>
422inline 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
428template <class Function, class A, class B, class C>
429inline 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
436template <class Function, class A, class B, class C, class D>
437inline 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
445template <class Function, class A, class B, class C, class D, class E>
446inline 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.
500template <class T, typename Method>
501class CallbackStorage {
502 public:
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.
513template <typename Params>
514class CallbackRunner {
515 public:
516  typedef Params TupleType;
517
518  virtual ~CallbackRunner() {}
519  virtual void RunWithParams(const Params& params) = 0;
520
521  // Convenience functions so callers don't have to deal with Tuples.
522  inline void Run() {
523    RunWithParams(Tuple0());
524  }
525
526  template <typename Arg1>
527  inline void Run(const Arg1& a) {
528    RunWithParams(Params(a));
529  }
530
531  template <typename Arg1, typename Arg2>
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>
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>
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>
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
554template <class T, typename Method, typename Params>
555class CallbackImpl : public CallbackStorage<T, Method>,
556                     public CallbackRunner<Params> {
557 public:
558  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
559  }
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
568struct Callback0 {
569  typedef CallbackRunner<Tuple0> Type;
570};
571
572template <class T>
573typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
574  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
575}
576
577// 1-arg implementation
578template <typename Arg1>
579struct Callback1 {
580  typedef CallbackRunner<Tuple1<Arg1> > Type;
581};
582
583template <class T, typename Arg1>
584typename 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
590template <typename Arg1, typename Arg2>
591struct Callback2 {
592  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
593};
594
595template <class T, typename Arg1, typename Arg2>
596typename 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
604template <typename Arg1, typename Arg2, typename Arg3>
605struct Callback3 {
606  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
607};
608
609template <class T, typename Arg1, typename Arg2, typename Arg3>
610typename 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
618template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
619struct Callback4 {
620  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
621};
622
623template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
624typename 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
632template <typename Arg1, typename Arg2, typename Arg3,
633          typename Arg4, typename Arg5>
634struct Callback5 {
635  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
636};
637
638template <class T, typename Arg1, typename Arg2,
639          typename Arg3, typename Arg4, typename Arg5>
640typename 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.
649template <class T, class Method, class Params>
650class UnboundMethod {
651 public:
652  UnboundMethod(Method m, Params p) : m_(m), p_(p) {
653    COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
654                   badunboundmethodparams);
655  }
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.
665template <typename ReturnValue>
666struct CallbackWithReturnValue {
667  class Type {
668   public:
669    virtual ~Type() {}
670    virtual ReturnValue Run() = 0;
671  };
672};
673
674template <class T, typename Method, typename ReturnValue>
675class CallbackWithReturnValueImpl
676    : public CallbackStorage<T, Method>,
677      public CallbackWithReturnValue<ReturnValue>::Type {
678 public:
679  CallbackWithReturnValueImpl(T* obj, Method meth)
680      : CallbackStorage<T, Method>(obj, meth) {}
681
682  virtual ReturnValue Run() {
683    return (this->obj_->*(this->meth_))();
684  }
685
686 protected:
687  virtual ~CallbackWithReturnValueImpl() {}
688};
689
690template <class T, typename ReturnValue>
691typename CallbackWithReturnValue<ReturnValue>::Type*
692NewCallbackWithReturnValue(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