1// Copyright (c) 2011 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/base_api.h"
10#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
11#include "base/memory/weak_ptr.h"
12#include "base/tracked.h"
13#include "base/tuple.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 BASE_API 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 BASE_API 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(
153          (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
154          badscopedrunnablemethodparams);
155    }
156
157    virtual void Run() {
158      if (obj_)
159        DispatchToMethod(obj_.get(), meth_, params_);
160    }
161
162    virtual void Cancel() {
163      obj_.reset();
164    }
165
166   private:
167    base::WeakPtr<T> obj_;
168    Method meth_;
169    Params params_;
170
171    DISALLOW_COPY_AND_ASSIGN(RunnableMethod);
172  };
173
174 private:
175  base::WeakPtrFactory<T> weak_factory_;
176};
177
178// General task implementations ------------------------------------------------
179
180// Task to delete an object
181template<class T>
182class DeleteTask : public CancelableTask {
183 public:
184  explicit DeleteTask(const T* obj) : obj_(obj) {
185  }
186  virtual void Run() {
187    delete obj_;
188  }
189  virtual void Cancel() {
190    obj_ = NULL;
191  }
192
193 private:
194  const T* obj_;
195};
196
197// Task to Release() an object
198template<class T>
199class ReleaseTask : public CancelableTask {
200 public:
201  explicit ReleaseTask(const T* obj) : obj_(obj) {
202  }
203  virtual void Run() {
204    if (obj_)
205      obj_->Release();
206  }
207  virtual void Cancel() {
208    obj_ = NULL;
209  }
210
211 private:
212  const T* obj_;
213};
214
215// RunnableMethodTraits --------------------------------------------------------
216//
217// This traits-class is used by RunnableMethod to manage the lifetime of the
218// callee object.  By default, it is assumed that the callee supports AddRef
219// and Release methods.  A particular class can specialize this template to
220// define other lifetime management.  For example, if the callee is known to
221// live longer than the RunnableMethod object, then a RunnableMethodTraits
222// struct could be defined with empty RetainCallee and ReleaseCallee methods.
223//
224// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way
225// for declaring a RunnableMethodTraits that disables refcounting.
226
227template <class T>
228struct RunnableMethodTraits {
229  RunnableMethodTraits() {
230#ifndef NDEBUG
231    origin_thread_id_ = base::PlatformThread::CurrentId();
232#endif
233  }
234
235  ~RunnableMethodTraits() {
236#ifndef NDEBUG
237    // If destroyed on a separate thread, then we had better have been using
238    // thread-safe reference counting!
239    if (origin_thread_id_ != base::PlatformThread::CurrentId())
240      DCHECK(T::ImplementsThreadSafeReferenceCounting());
241#endif
242  }
243
244  void RetainCallee(T* obj) {
245#ifndef NDEBUG
246    // Catch NewRunnableMethod being called in an object's constructor.  This
247    // isn't safe since the method can be invoked before the constructor
248    // completes, causing the object to be deleted.
249    obj->AddRef();
250    obj->Release();
251#endif
252    obj->AddRef();
253  }
254
255  void ReleaseCallee(T* obj) {
256    obj->Release();
257  }
258
259 private:
260#ifndef NDEBUG
261  base::PlatformThreadId origin_thread_id_;
262#endif
263};
264
265// Convenience macro for declaring a RunnableMethodTraits that disables
266// refcounting of a class.  This is useful if you know that the callee
267// will outlive the RunnableMethod object and thus do not need the ref counts.
268//
269// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the
270// global namespace scope.  Example:
271//
272//   namespace foo {
273//   class Bar {
274//     ...
275//   };
276//   }  // namespace foo
277//
278//   DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar);
279//
280// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the
281// class.
282#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \
283  template <>                                      \
284  struct RunnableMethodTraits<TypeName> {          \
285    void RetainCallee(TypeName* manager) {}        \
286    void ReleaseCallee(TypeName* manager) {}       \
287  }
288
289// RunnableMethod and RunnableFunction -----------------------------------------
290//
291// Runnable methods are a type of task that call a function on an object when
292// they are run. We implement both an object and a set of NewRunnableMethod and
293// NewRunnableFunction functions for convenience. These functions are
294// overloaded and will infer the template types, simplifying calling code.
295//
296// The template definitions all use the following names:
297// T                - the class type of the object you're supplying
298//                    this is not needed for the Static version of the call
299// Method/Function  - the signature of a pointer to the method or function you
300//                    want to call
301// Param            - the parameter(s) to the method, possibly packed as a Tuple
302// A                - the first parameter (if any) to the method
303// B                - the second parameter (if any) to the method
304//
305// Put these all together and you get an object that can call a method whose
306// signature is:
307//   R T::MyFunction([A[, B]])
308//
309// Usage:
310// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])
311// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
312
313// RunnableMethod and NewRunnableMethod implementation -------------------------
314
315template <class T, class Method, class Params>
316class RunnableMethod : public CancelableTask {
317 public:
318  RunnableMethod(T* obj, Method meth, const Params& params)
319      : obj_(obj), meth_(meth), params_(params) {
320    traits_.RetainCallee(obj_);
321    COMPILE_ASSERT(
322        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
323        badrunnablemethodparams);
324  }
325
326  ~RunnableMethod() {
327    ReleaseCallee();
328  }
329
330  virtual void Run() {
331    if (obj_)
332      DispatchToMethod(obj_, meth_, params_);
333  }
334
335  virtual void Cancel() {
336    ReleaseCallee();
337  }
338
339 private:
340  void ReleaseCallee() {
341    T* obj = obj_;
342    obj_ = NULL;
343    if (obj)
344      traits_.ReleaseCallee(obj);
345  }
346
347  T* obj_;
348  Method meth_;
349  Params params_;
350  RunnableMethodTraits<T> traits_;
351};
352
353template <class T, class Method>
354inline CancelableTask* NewRunnableMethod(T* object, Method method) {
355  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
356}
357
358template <class T, class Method, class A>
359inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
360  return new RunnableMethod<T, Method, Tuple1<A> >(object,
361                                                   method,
362                                                   MakeTuple(a));
363}
364
365template <class T, class Method, class A, class B>
366inline CancelableTask* NewRunnableMethod(T* object, Method method,
367const A& a, const B& b) {
368  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
369                                                      MakeTuple(a, b));
370}
371
372template <class T, class Method, class A, class B, class C>
373inline CancelableTask* NewRunnableMethod(T* object, Method method,
374                                          const A& a, const B& b, const C& c) {
375  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
376                                                         MakeTuple(a, b, c));
377}
378
379template <class T, class Method, class A, class B, class C, class D>
380inline CancelableTask* NewRunnableMethod(T* object, Method method,
381                                          const A& a, const B& b,
382                                          const C& c, const D& d) {
383  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
384                                                            MakeTuple(a, b,
385                                                                      c, d));
386}
387
388template <class T, class Method, class A, class B, class C, class D, class E>
389inline CancelableTask* NewRunnableMethod(T* object, Method method,
390                                          const A& a, const B& b,
391                                          const C& c, const D& d, const E& e) {
392  return new RunnableMethod<T,
393                            Method,
394                            Tuple5<A, B, C, D, E> >(object,
395                                                    method,
396                                                    MakeTuple(a, b, c, d, e));
397}
398
399template <class T, class Method, class A, class B, class C, class D, class E,
400          class F>
401inline CancelableTask* NewRunnableMethod(T* object, Method method,
402                                          const A& a, const B& b,
403                                          const C& c, const D& d, const E& e,
404                                          const F& f) {
405  return new RunnableMethod<T,
406                            Method,
407                            Tuple6<A, B, C, D, E, F> >(object,
408                                                       method,
409                                                       MakeTuple(a, b, c, d, e,
410                                                                 f));
411}
412
413template <class T, class Method, class A, class B, class C, class D, class E,
414          class F, class G>
415inline CancelableTask* NewRunnableMethod(T* object, Method method,
416                                         const A& a, const B& b,
417                                         const C& c, const D& d, const E& e,
418                                         const F& f, const G& g) {
419  return new RunnableMethod<T,
420                            Method,
421                            Tuple7<A, B, C, D, E, F, G> >(object,
422                                                          method,
423                                                          MakeTuple(a, b, c, d,
424                                                                    e, f, g));
425}
426
427template <class T, class Method, class A, class B, class C, class D, class E,
428          class F, class G, class H>
429inline CancelableTask* NewRunnableMethod(T* object, Method method,
430                                         const A& a, const B& b,
431                                         const C& c, const D& d, const E& e,
432                                         const F& f, const G& g, const H& h) {
433  return new RunnableMethod<T,
434                            Method,
435                            Tuple8<A, B, C, D, E, F, G, H> >(object,
436                                                             method,
437                                                             MakeTuple(a, b, c,
438                                                                       d, e, f,
439                                                                       g, h));
440}
441
442// RunnableFunction and NewRunnableFunction implementation ---------------------
443
444template <class Function, class Params>
445class RunnableFunction : public CancelableTask {
446 public:
447  RunnableFunction(Function function, const Params& params)
448      : function_(function), params_(params) {
449    COMPILE_ASSERT(
450        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
451        badrunnablefunctionparams);
452  }
453
454  ~RunnableFunction() {
455  }
456
457  virtual void Run() {
458    if (function_)
459      DispatchToFunction(function_, params_);
460  }
461
462  virtual void Cancel() {
463  }
464
465 private:
466  Function function_;
467  Params params_;
468};
469
470template <class Function>
471inline CancelableTask* NewRunnableFunction(Function function) {
472  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
473}
474
475template <class Function, class A>
476inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
477  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
478}
479
480template <class Function, class A, class B>
481inline CancelableTask* NewRunnableFunction(Function function,
482                                           const A& a, const B& b) {
483  return new RunnableFunction<Function, Tuple2<A, B> >(function,
484                                                       MakeTuple(a, b));
485}
486
487template <class Function, class A, class B, class C>
488inline CancelableTask* NewRunnableFunction(Function function,
489                                           const A& a, const B& b,
490                                           const C& c) {
491  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
492                                                          MakeTuple(a, b, c));
493}
494
495template <class Function, class A, class B, class C, class D>
496inline CancelableTask* NewRunnableFunction(Function function,
497                                           const A& a, const B& b,
498                                           const C& c, const D& d) {
499  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
500                                                             MakeTuple(a, b,
501                                                                       c, d));
502}
503
504template <class Function, class A, class B, class C, class D, class E>
505inline CancelableTask* NewRunnableFunction(Function function,
506                                           const A& a, const B& b,
507                                           const C& c, const D& d,
508                                           const E& e) {
509  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
510                                                                MakeTuple(a, b,
511                                                                          c, d,
512                                                                          e));
513}
514
515template <class Function, class A, class B, class C, class D, class E,
516          class F>
517inline CancelableTask* NewRunnableFunction(Function function,
518                                           const A& a, const B& b,
519                                           const C& c, const D& d,
520                                           const E& e, const F& f) {
521  return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function,
522      MakeTuple(a, b, c, d, e, f));
523}
524
525template <class Function, class A, class B, class C, class D, class E,
526          class F, class G>
527inline CancelableTask* NewRunnableFunction(Function function,
528                                           const A& a, const B& b,
529                                           const C& c, const D& d,
530                                           const E& e, const F& f,
531                                           const G& g) {
532  return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function,
533      MakeTuple(a, b, c, d, e, f, g));
534}
535
536template <class Function, class A, class B, class C, class D, class E,
537          class F, class G, class H>
538inline CancelableTask* NewRunnableFunction(Function function,
539                                           const A& a, const B& b,
540                                           const C& c, const D& d,
541                                           const E& e, const F& f,
542                                           const G& g, const H& h) {
543  return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >(
544      function, MakeTuple(a, b, c, d, e, f, g, h));
545}
546
547#endif  // BASE_TASK_H_
548