task.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
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/non_thread_safe.h"
10#include "base/raw_scoped_refptr_mismatch_checker.h"
11#include "base/tracked.h"
12#include "base/tuple.h"
13#include "base/weak_ptr.h"
14
15// Task ------------------------------------------------------------------------
16//
17// A task is a generic runnable thingy, usually used for running code on a
18// different thread or for scheduling future tasks off of the message loop.
19
20class Task : public tracked_objects::Tracked {
21 public:
22  Task();
23  virtual ~Task();
24
25  // Tasks are automatically deleted after Run is called.
26  virtual void Run() = 0;
27};
28
29class CancelableTask : public Task {
30 public:
31  CancelableTask();
32  virtual ~CancelableTask();
33
34  // Not all tasks support cancellation.
35  virtual void Cancel() = 0;
36};
37
38// Scoped Factories ------------------------------------------------------------
39//
40// These scoped factory objects can be used by non-refcounted objects to safely
41// place tasks in a message loop.  Each factory guarantees that the tasks it
42// produces will not run after the factory is destroyed.  Commonly, factories
43// are declared as class members, so the class' tasks will automatically cancel
44// when the class instance is destroyed.
45//
46// Exampe Usage:
47//
48// class MyClass {
49//  private:
50//   // This factory will be used to schedule invocations of SomeMethod.
51//   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
52//
53//  public:
54//   // It is safe to suppress warning 4355 here.
55//   MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { }
56//
57//   void SomeMethod() {
58//     // If this function might be called directly, you might want to revoke
59//     // any outstanding runnable methods scheduled to call it.  If it's not
60//     // referenced other than by the factory, this is unnecessary.
61//     some_method_factory_.RevokeAll();
62//     ...
63//   }
64//
65//   void ScheduleSomeMethod() {
66//     // If you'd like to only only have one pending task at a time, test for
67//     // |empty| before manufacturing another task.
68//     if (!some_method_factory_.empty())
69//       return;
70//
71//     // The factories are not thread safe, so always invoke on
72//     // |MessageLoop::current()|.
73//     MessageLoop::current()->PostDelayedTask(
74//         FROM_HERE,
75//         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
76//         kSomeMethodDelayMS);
77//   }
78// };
79
80// A ScopedRunnableMethodFactory creates runnable methods for a specified
81// object.  This is particularly useful for generating callbacks for
82// non-reference counted objects when the factory is a member of the object.
83template<class T>
84class ScopedRunnableMethodFactory {
85 public:
86  explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) {
87  }
88
89  template <class Method>
90  inline CancelableTask* NewRunnableMethod(Method method) {
91    return new RunnableMethod<Method, Tuple0>(
92        weak_factory_.GetWeakPtr(), method, MakeTuple());
93  }
94
95  template <class Method, class A>
96  inline CancelableTask* NewRunnableMethod(Method method, const A& a) {
97    return new RunnableMethod<Method, Tuple1<A> >(
98        weak_factory_.GetWeakPtr(), method, MakeTuple(a));
99  }
100
101  template <class Method, class A, class B>
102  inline CancelableTask* NewRunnableMethod(Method method, const A& a,
103                                           const B& b) {
104    return new RunnableMethod<Method, Tuple2<A, B> >(
105        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b));
106  }
107
108  template <class Method, class A, class B, class C>
109  inline CancelableTask* NewRunnableMethod(Method method,
110                                           const A& a,
111                                           const B& b,
112                                           const C& c) {
113    return new RunnableMethod<Method, Tuple3<A, B, C> >(
114        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c));
115  }
116
117  template <class Method, class A, class B, class C, class D>
118  inline CancelableTask* NewRunnableMethod(Method method,
119                                           const A& a,
120                                           const B& b,
121                                           const C& c,
122                                           const D& d) {
123    return new RunnableMethod<Method, Tuple4<A, B, C, D> >(
124        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d));
125  }
126
127  template <class Method, class A, class B, class C, class D, class E>
128  inline CancelableTask* NewRunnableMethod(Method method,
129                                           const A& a,
130                                           const B& b,
131                                           const C& c,
132                                           const D& d,
133                                           const E& e) {
134    return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >(
135        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e));
136  }
137
138  void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
139
140  bool empty() const { return !weak_factory_.HasWeakPtrs(); }
141
142 protected:
143  template <class Method, class Params>
144  class RunnableMethod : public CancelableTask {
145   public:
146    RunnableMethod(const base::WeakPtr<T>& obj,
147                   Method meth,
148                   const Params& params)
149        : obj_(obj),
150          meth_(meth),
151          params_(params) {
152      COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, 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(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  T* obj_;
194};
195
196// Task to Release() an object
197template<class T>
198class ReleaseTask : public CancelableTask {
199 public:
200  explicit ReleaseTask(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  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_ = 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_ != 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  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((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
321                   badrunnablemethodparams);
322  }
323
324  ~RunnableMethod() {
325    ReleaseCallee();
326  }
327
328  virtual void Run() {
329    if (obj_)
330      DispatchToMethod(obj_, meth_, params_);
331  }
332
333  virtual void Cancel() {
334    ReleaseCallee();
335  }
336
337 private:
338  void ReleaseCallee() {
339    if (obj_) {
340      traits_.ReleaseCallee(obj_);
341      obj_ = NULL;
342    }
343  }
344
345  T* obj_;
346  Method meth_;
347  Params params_;
348  RunnableMethodTraits<T> traits_;
349};
350
351template <class T, class Method>
352inline CancelableTask* NewRunnableMethod(T* object, Method method) {
353  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
354}
355
356template <class T, class Method, class A>
357inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
358  return new RunnableMethod<T, Method, Tuple1<A> >(object,
359                                                   method,
360                                                   MakeTuple(a));
361}
362
363template <class T, class Method, class A, class B>
364inline CancelableTask* NewRunnableMethod(T* object, Method method,
365const A& a, const B& b) {
366  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
367                                                      MakeTuple(a, b));
368}
369
370template <class T, class Method, class A, class B, class C>
371inline CancelableTask* NewRunnableMethod(T* object, Method method,
372                                          const A& a, const B& b, const C& c) {
373  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
374                                                         MakeTuple(a, b, c));
375}
376
377template <class T, class Method, class A, class B, class C, class D>
378inline CancelableTask* NewRunnableMethod(T* object, Method method,
379                                          const A& a, const B& b,
380                                          const C& c, const D& d) {
381  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
382                                                            MakeTuple(a, b,
383                                                                      c, d));
384}
385
386template <class T, class Method, class A, class B, class C, class D, class E>
387inline CancelableTask* NewRunnableMethod(T* object, Method method,
388                                          const A& a, const B& b,
389                                          const C& c, const D& d, const E& e) {
390  return new RunnableMethod<T,
391                            Method,
392                            Tuple5<A, B, C, D, E> >(object,
393                                                    method,
394                                                    MakeTuple(a, b, c, d, e));
395}
396
397template <class T, class Method, class A, class B, class C, class D, class E,
398          class F>
399inline CancelableTask* NewRunnableMethod(T* object, Method method,
400                                          const A& a, const B& b,
401                                          const C& c, const D& d, const E& e,
402                                          const F& f) {
403  return new RunnableMethod<T,
404                            Method,
405                            Tuple6<A, B, C, D, E, F> >(object,
406                                                       method,
407                                                       MakeTuple(a, b, c, d, e,
408                                                                 f));
409}
410
411template <class T, class Method, class A, class B, class C, class D, class E,
412          class F, class G>
413inline CancelableTask* NewRunnableMethod(T* object, Method method,
414                                         const A& a, const B& b,
415                                         const C& c, const D& d, const E& e,
416                                         const F& f, const G& g) {
417  return new RunnableMethod<T,
418                            Method,
419                            Tuple7<A, B, C, D, E, F, G> >(object,
420                                                          method,
421                                                          MakeTuple(a, b, c, d,
422                                                                    e, f, g));
423}
424
425// RunnableFunction and NewRunnableFunction implementation ---------------------
426
427template <class Function, class Params>
428class RunnableFunction : public CancelableTask {
429 public:
430  RunnableFunction(Function function, const Params& params)
431      : function_(function), params_(params) {
432    COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value),
433                   badrunnablefunctionparams);
434  }
435
436  ~RunnableFunction() {
437  }
438
439  virtual void Run() {
440    if (function_)
441      DispatchToFunction(function_, params_);
442  }
443
444  virtual void Cancel() {
445  }
446
447 private:
448  Function function_;
449  Params params_;
450};
451
452template <class Function>
453inline CancelableTask* NewRunnableFunction(Function function) {
454  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
455}
456
457template <class Function, class A>
458inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
459  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
460}
461
462template <class Function, class A, class B>
463inline CancelableTask* NewRunnableFunction(Function function,
464                                           const A& a, const B& b) {
465  return new RunnableFunction<Function, Tuple2<A, B> >(function,
466                                                       MakeTuple(a, b));
467}
468
469template <class Function, class A, class B, class C>
470inline CancelableTask* NewRunnableFunction(Function function,
471                                           const A& a, const B& b,
472                                           const C& c) {
473  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
474                                                          MakeTuple(a, b, c));
475}
476
477template <class Function, class A, class B, class C, class D>
478inline CancelableTask* NewRunnableFunction(Function function,
479                                           const A& a, const B& b,
480                                           const C& c, const D& d) {
481  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
482                                                             MakeTuple(a, b,
483                                                                       c, d));
484}
485
486template <class Function, class A, class B, class C, class D, class E>
487inline CancelableTask* NewRunnableFunction(Function function,
488                                           const A& a, const B& b,
489                                           const C& c, const D& d,
490                                           const E& e) {
491  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
492                                                                MakeTuple(a, b,
493                                                                          c, d,
494                                                                          e));
495}
496
497template <class Function, class A, class B, class C, class D, class E,
498          class F>
499inline CancelableTask* NewRunnableFunction(Function function,
500                                           const A& a, const B& b,
501                                           const C& c, const D& d,
502                                           const E& e, const F& f) {
503  return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function,
504      MakeTuple(a, b, c, d, e, f));
505}
506
507template <class Function, class A, class B, class C, class D, class E,
508          class F, class G>
509inline CancelableTask* NewRunnableFunction(Function function,
510                                           const A& a, const B& b,
511                                           const C& c, const D& d,
512                                           const E& e, const F& f,
513                                           const G& g) {
514  return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function,
515      MakeTuple(a, b, c, d, e, f, g));
516}
517
518template <class Function, class A, class B, class C, class D, class E,
519          class F, class G, class H>
520inline CancelableTask* NewRunnableFunction(Function function,
521                                           const A& a, const B& b,
522                                           const C& c, const D& d,
523                                           const E& e, const F& f,
524                                           const G& g, const H& h) {
525  return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >(
526      function, MakeTuple(a, b, c, d, e, f, g, h));
527}
528
529#endif  // BASE_TASK_H_
530