task.h revision 3f50c38dc070f4bb515c1b64450dae14f316474e
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#pragma once
8
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  CancelableTask();
31  virtual ~CancelableTask();
32
33  // Not all tasks support cancellation.
34  virtual void Cancel() = 0;
35};
36
37// Scoped Factories ------------------------------------------------------------
38//
39// These scoped factory objects can be used by non-refcounted objects to safely
40// place tasks in a message loop.  Each factory guarantees that the tasks it
41// produces will not run after the factory is destroyed.  Commonly, factories
42// are declared as class members, so the class' tasks will automatically cancel
43// when the class instance is destroyed.
44//
45// Exampe Usage:
46//
47// class MyClass {
48//  private:
49//   // This factory will be used to schedule invocations of SomeMethod.
50//   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
51//
52//  public:
53//   // It is safe to suppress warning 4355 here.
54//   MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { }
55//
56//   void SomeMethod() {
57//     // If this function might be called directly, you might want to revoke
58//     // any outstanding runnable methods scheduled to call it.  If it's not
59//     // referenced other than by the factory, this is unnecessary.
60//     some_method_factory_.RevokeAll();
61//     ...
62//   }
63//
64//   void ScheduleSomeMethod() {
65//     // If you'd like to only only have one pending task at a time, test for
66//     // |empty| before manufacturing another task.
67//     if (!some_method_factory_.empty())
68//       return;
69//
70//     // The factories are not thread safe, so always invoke on
71//     // |MessageLoop::current()|.
72//     MessageLoop::current()->PostDelayedTask(
73//         FROM_HERE,
74//         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
75//         kSomeMethodDelayMS);
76//   }
77// };
78
79// A ScopedRunnableMethodFactory creates runnable methods for a specified
80// object.  This is particularly useful for generating callbacks for
81// non-reference counted objects when the factory is a member of the object.
82template<class T>
83class ScopedRunnableMethodFactory {
84 public:
85  explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) {
86  }
87
88  template <class Method>
89  inline CancelableTask* NewRunnableMethod(Method method) {
90    return new RunnableMethod<Method, Tuple0>(
91        weak_factory_.GetWeakPtr(), method, MakeTuple());
92  }
93
94  template <class Method, class A>
95  inline CancelableTask* NewRunnableMethod(Method method, const A& a) {
96    return new RunnableMethod<Method, Tuple1<A> >(
97        weak_factory_.GetWeakPtr(), method, MakeTuple(a));
98  }
99
100  template <class Method, class A, class B>
101  inline CancelableTask* NewRunnableMethod(Method method, const A& a,
102                                           const B& b) {
103    return new RunnableMethod<Method, Tuple2<A, B> >(
104        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b));
105  }
106
107  template <class Method, class A, class B, class C>
108  inline CancelableTask* NewRunnableMethod(Method method,
109                                           const A& a,
110                                           const B& b,
111                                           const C& c) {
112    return new RunnableMethod<Method, Tuple3<A, B, C> >(
113        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c));
114  }
115
116  template <class Method, class A, class B, class C, class D>
117  inline CancelableTask* NewRunnableMethod(Method method,
118                                           const A& a,
119                                           const B& b,
120                                           const C& c,
121                                           const D& d) {
122    return new RunnableMethod<Method, Tuple4<A, B, C, D> >(
123        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d));
124  }
125
126  template <class Method, class A, class B, class C, class D, class E>
127  inline CancelableTask* NewRunnableMethod(Method method,
128                                           const A& a,
129                                           const B& b,
130                                           const C& c,
131                                           const D& d,
132                                           const E& e) {
133    return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >(
134        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e));
135  }
136
137  void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
138
139  bool empty() const { return !weak_factory_.HasWeakPtrs(); }
140
141 protected:
142  template <class Method, class Params>
143  class RunnableMethod : public CancelableTask {
144   public:
145    RunnableMethod(const base::WeakPtr<T>& obj,
146                   Method meth,
147                   const Params& params)
148        : obj_(obj),
149          meth_(meth),
150          params_(params) {
151      COMPILE_ASSERT(
152          (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
153          badscopedrunnablemethodparams);
154    }
155
156    virtual void Run() {
157      if (obj_)
158        DispatchToMethod(obj_.get(), meth_, params_);
159    }
160
161    virtual void Cancel() {
162      obj_.reset();
163    }
164
165   private:
166    base::WeakPtr<T> obj_;
167    Method meth_;
168    Params params_;
169
170    DISALLOW_COPY_AND_ASSIGN(RunnableMethod);
171  };
172
173 private:
174  base::WeakPtrFactory<T> weak_factory_;
175};
176
177// General task implementations ------------------------------------------------
178
179// Task to delete an object
180template<class T>
181class DeleteTask : public CancelableTask {
182 public:
183  explicit DeleteTask(const T* obj) : obj_(obj) {
184  }
185  virtual void Run() {
186    delete obj_;
187  }
188  virtual void Cancel() {
189    obj_ = NULL;
190  }
191
192 private:
193  const T* obj_;
194};
195
196// Task to Release() an object
197template<class T>
198class ReleaseTask : public CancelableTask {
199 public:
200  explicit ReleaseTask(const T* obj) : obj_(obj) {
201  }
202  virtual void Run() {
203    if (obj_)
204      obj_->Release();
205  }
206  virtual void Cancel() {
207    obj_ = NULL;
208  }
209
210 private:
211  const T* obj_;
212};
213
214// RunnableMethodTraits --------------------------------------------------------
215//
216// This traits-class is used by RunnableMethod to manage the lifetime of the
217// callee object.  By default, it is assumed that the callee supports AddRef
218// and Release methods.  A particular class can specialize this template to
219// define other lifetime management.  For example, if the callee is known to
220// live longer than the RunnableMethod object, then a RunnableMethodTraits
221// struct could be defined with empty RetainCallee and ReleaseCallee methods.
222//
223// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way
224// for declaring a RunnableMethodTraits that disables refcounting.
225
226template <class T>
227struct RunnableMethodTraits {
228  RunnableMethodTraits() {
229#ifndef NDEBUG
230    origin_thread_id_ = base::PlatformThread::CurrentId();
231#endif
232  }
233
234  ~RunnableMethodTraits() {
235#ifndef NDEBUG
236    // If destroyed on a separate thread, then we had better have been using
237    // thread-safe reference counting!
238    if (origin_thread_id_ != base::PlatformThread::CurrentId())
239      DCHECK(T::ImplementsThreadSafeReferenceCounting());
240#endif
241  }
242
243  void RetainCallee(T* obj) {
244#ifndef NDEBUG
245    // Catch NewRunnableMethod being called in an object's constructor.  This
246    // isn't safe since the method can be invoked before the constructor
247    // completes, causing the object to be deleted.
248    obj->AddRef();
249    obj->Release();
250#endif
251    obj->AddRef();
252  }
253
254  void ReleaseCallee(T* obj) {
255    obj->Release();
256  }
257
258 private:
259#ifndef NDEBUG
260  base::PlatformThreadId origin_thread_id_;
261#endif
262};
263
264// Convenience macro for declaring a RunnableMethodTraits that disables
265// refcounting of a class.  This is useful if you know that the callee
266// will outlive the RunnableMethod object and thus do not need the ref counts.
267//
268// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the
269// global namespace scope.  Example:
270//
271//   namespace foo {
272//   class Bar {
273//     ...
274//   };
275//   }  // namespace foo
276//
277//   DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar);
278//
279// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the
280// class.
281#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \
282  template <>                                      \
283  struct RunnableMethodTraits<TypeName> {          \
284    void RetainCallee(TypeName* manager) {}        \
285    void ReleaseCallee(TypeName* manager) {}       \
286  }
287
288// RunnableMethod and RunnableFunction -----------------------------------------
289//
290// Runnable methods are a type of task that call a function on an object when
291// they are run. We implement both an object and a set of NewRunnableMethod and
292// NewRunnableFunction functions for convenience. These functions are
293// overloaded and will infer the template types, simplifying calling code.
294//
295// The template definitions all use the following names:
296// T                - the class type of the object you're supplying
297//                    this is not needed for the Static version of the call
298// Method/Function  - the signature of a pointer to the method or function you
299//                    want to call
300// Param            - the parameter(s) to the method, possibly packed as a Tuple
301// A                - the first parameter (if any) to the method
302// B                - the second parameter (if any) to the method
303//
304// Put these all together and you get an object that can call a method whose
305// signature is:
306//   R T::MyFunction([A[, B]])
307//
308// Usage:
309// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])
310// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
311
312// RunnableMethod and NewRunnableMethod implementation -------------------------
313
314template <class T, class Method, class Params>
315class RunnableMethod : public CancelableTask {
316 public:
317  RunnableMethod(T* obj, Method meth, const Params& params)
318      : obj_(obj), meth_(meth), params_(params) {
319    traits_.RetainCallee(obj_);
320    COMPILE_ASSERT(
321        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
322        badrunnablemethodparams);
323  }
324
325  ~RunnableMethod() {
326    ReleaseCallee();
327  }
328
329  virtual void Run() {
330    if (obj_)
331      DispatchToMethod(obj_, meth_, params_);
332  }
333
334  virtual void Cancel() {
335    ReleaseCallee();
336  }
337
338 private:
339  void ReleaseCallee() {
340    T* obj = obj_;
341    obj_ = NULL;
342    if (obj)
343      traits_.ReleaseCallee(obj);
344  }
345
346  T* obj_;
347  Method meth_;
348  Params params_;
349  RunnableMethodTraits<T> traits_;
350};
351
352template <class T, class Method>
353inline CancelableTask* NewRunnableMethod(T* object, Method method) {
354  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
355}
356
357template <class T, class Method, class A>
358inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
359  return new RunnableMethod<T, Method, Tuple1<A> >(object,
360                                                   method,
361                                                   MakeTuple(a));
362}
363
364template <class T, class Method, class A, class B>
365inline CancelableTask* NewRunnableMethod(T* object, Method method,
366const A& a, const B& b) {
367  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
368                                                      MakeTuple(a, b));
369}
370
371template <class T, class Method, class A, class B, class C>
372inline CancelableTask* NewRunnableMethod(T* object, Method method,
373                                          const A& a, const B& b, const C& c) {
374  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
375                                                         MakeTuple(a, b, c));
376}
377
378template <class T, class Method, class A, class B, class C, class D>
379inline CancelableTask* NewRunnableMethod(T* object, Method method,
380                                          const A& a, const B& b,
381                                          const C& c, const D& d) {
382  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
383                                                            MakeTuple(a, b,
384                                                                      c, d));
385}
386
387template <class T, class Method, class A, class B, class C, class D, class E>
388inline CancelableTask* NewRunnableMethod(T* object, Method method,
389                                          const A& a, const B& b,
390                                          const C& c, const D& d, const E& e) {
391  return new RunnableMethod<T,
392                            Method,
393                            Tuple5<A, B, C, D, E> >(object,
394                                                    method,
395                                                    MakeTuple(a, b, c, d, e));
396}
397
398template <class T, class Method, class A, class B, class C, class D, class E,
399          class F>
400inline CancelableTask* NewRunnableMethod(T* object, Method method,
401                                          const A& a, const B& b,
402                                          const C& c, const D& d, const E& e,
403                                          const F& f) {
404  return new RunnableMethod<T,
405                            Method,
406                            Tuple6<A, B, C, D, E, F> >(object,
407                                                       method,
408                                                       MakeTuple(a, b, c, d, e,
409                                                                 f));
410}
411
412template <class T, class Method, class A, class B, class C, class D, class E,
413          class F, class G>
414inline CancelableTask* NewRunnableMethod(T* object, Method method,
415                                         const A& a, const B& b,
416                                         const C& c, const D& d, const E& e,
417                                         const F& f, const G& g) {
418  return new RunnableMethod<T,
419                            Method,
420                            Tuple7<A, B, C, D, E, F, G> >(object,
421                                                          method,
422                                                          MakeTuple(a, b, c, d,
423                                                                    e, f, g));
424}
425
426// RunnableFunction and NewRunnableFunction implementation ---------------------
427
428template <class Function, class Params>
429class RunnableFunction : public CancelableTask {
430 public:
431  RunnableFunction(Function function, const Params& params)
432      : function_(function), params_(params) {
433    COMPILE_ASSERT(
434        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
435        badrunnablefunctionparams);
436  }
437
438  ~RunnableFunction() {
439  }
440
441  virtual void Run() {
442    if (function_)
443      DispatchToFunction(function_, params_);
444  }
445
446  virtual void Cancel() {
447  }
448
449 private:
450  Function function_;
451  Params params_;
452};
453
454template <class Function>
455inline CancelableTask* NewRunnableFunction(Function function) {
456  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
457}
458
459template <class Function, class A>
460inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
461  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
462}
463
464template <class Function, class A, class B>
465inline CancelableTask* NewRunnableFunction(Function function,
466                                           const A& a, const B& b) {
467  return new RunnableFunction<Function, Tuple2<A, B> >(function,
468                                                       MakeTuple(a, b));
469}
470
471template <class Function, class A, class B, class C>
472inline CancelableTask* NewRunnableFunction(Function function,
473                                           const A& a, const B& b,
474                                           const C& c) {
475  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
476                                                          MakeTuple(a, b, c));
477}
478
479template <class Function, class A, class B, class C, class D>
480inline CancelableTask* NewRunnableFunction(Function function,
481                                           const A& a, const B& b,
482                                           const C& c, const D& d) {
483  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
484                                                             MakeTuple(a, b,
485                                                                       c, d));
486}
487
488template <class Function, class A, class B, class C, class D, class E>
489inline CancelableTask* NewRunnableFunction(Function function,
490                                           const A& a, const B& b,
491                                           const C& c, const D& d,
492                                           const E& e) {
493  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
494                                                                MakeTuple(a, b,
495                                                                          c, d,
496                                                                          e));
497}
498
499template <class Function, class A, class B, class C, class D, class E,
500          class F>
501inline CancelableTask* NewRunnableFunction(Function function,
502                                           const A& a, const B& b,
503                                           const C& c, const D& d,
504                                           const E& e, const F& f) {
505  return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function,
506      MakeTuple(a, b, c, d, e, f));
507}
508
509template <class Function, class A, class B, class C, class D, class E,
510          class F, class G>
511inline CancelableTask* NewRunnableFunction(Function function,
512                                           const A& a, const B& b,
513                                           const C& c, const D& d,
514                                           const E& e, const F& f,
515                                           const G& g) {
516  return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function,
517      MakeTuple(a, b, c, d, e, f, g));
518}
519
520template <class Function, class A, class B, class C, class D, class E,
521          class F, class G, class H>
522inline CancelableTask* NewRunnableFunction(Function function,
523                                           const A& a, const B& b,
524                                           const C& c, const D& d,
525                                           const E& e, const F& f,
526                                           const G& g, const H& h) {
527  return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >(
528      function, MakeTuple(a, b, c, d, e, f, g, h));
529}
530
531#endif  // BASE_TASK_H_
532