Home | History | Annotate | Download | only in base
      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 
     20 class 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 
     29 class 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.
     83 template<class T>
     84 class 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
    181 template<class T>
    182 class 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
    198 template<class T>
    199 class 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 
    227 template <class T>
    228 struct 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 
    315 template <class T, class Method, class Params>
    316 class 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 
    353 template <class T, class Method>
    354 inline CancelableTask* NewRunnableMethod(T* object, Method method) {
    355   return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
    356 }
    357 
    358 template <class T, class Method, class A>
    359 inline 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 
    365 template <class T, class Method, class A, class B>
    366 inline CancelableTask* NewRunnableMethod(T* object, Method method,
    367 const A& a, const B& b) {
    368   return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
    369                                                       MakeTuple(a, b));
    370 }
    371 
    372 template <class T, class Method, class A, class B, class C>
    373 inline 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 
    379 template <class T, class Method, class A, class B, class C, class D>
    380 inline 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 
    388 template <class T, class Method, class A, class B, class C, class D, class E>
    389 inline 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 
    399 template <class T, class Method, class A, class B, class C, class D, class E,
    400           class F>
    401 inline 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 
    413 template <class T, class Method, class A, class B, class C, class D, class E,
    414           class F, class G>
    415 inline 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 
    427 template <class T, class Method, class A, class B, class C, class D, class E,
    428           class F, class G, class H>
    429 inline 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 
    444 template <class Function, class Params>
    445 class 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 
    470 template <class Function>
    471 inline CancelableTask* NewRunnableFunction(Function function) {
    472   return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
    473 }
    474 
    475 template <class Function, class A>
    476 inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
    477   return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
    478 }
    479 
    480 template <class Function, class A, class B>
    481 inline 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 
    487 template <class Function, class A, class B, class C>
    488 inline 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 
    495 template <class Function, class A, class B, class C, class D>
    496 inline 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 
    504 template <class Function, class A, class B, class C, class D, class E>
    505 inline 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 
    515 template <class Function, class A, class B, class C, class D, class E,
    516           class F>
    517 inline 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 
    525 template <class Function, class A, class B, class C, class D, class E,
    526           class F, class G>
    527 inline 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 
    536 template <class Function, class A, class B, class C, class D, class E,
    537           class F, class G, class H>
    538 inline 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