LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - task.h (source / functions) Found Hit Coverage
Test: app.info Lines: 82 10 12.2 %
Date: 2012-06-02 Functions: 228 6 2.6 %

       1                 : // Copyright (c) 2006-2008 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/revocable_store.h"
      10                 : #include "base/tracked.h"
      11                 : #include "base/tuple.h"
      12                 : 
      13                 : // Task ------------------------------------------------------------------------
      14                 : //
      15                 : // A task is a generic runnable thingy, usually used for running code on a
      16                 : // different thread or for scheduling future tasks off of the message loop.
      17                 : 
      18                 : class Task : public tracked_objects::Tracked {
      19                 :  public:
      20            1420 :   Task() {}
      21            2838 :   virtual ~Task() {}
      22                 : 
      23                 :   // Tasks are automatically deleted after Run is called.
      24                 :   virtual void Run() = 0;
      25                 : };
      26                 : 
      27               1 : class CancelableTask : public Task {
      28                 :  public:
      29                 :   // Not all tasks support cancellation.
      30                 :   virtual void Cancel() = 0;
      31                 : };
      32                 : 
      33                 : // Scoped Factories ------------------------------------------------------------
      34                 : //
      35                 : // These scoped factory objects can be used by non-refcounted objects to safely
      36                 : // place tasks in a message loop.  Each factory guarantees that the tasks it
      37                 : // produces will not run after the factory is destroyed.  Commonly, factories
      38                 : // are declared as class members, so the class' tasks will automatically cancel
      39                 : // when the class instance is destroyed.
      40                 : //
      41                 : // Exampe Usage:
      42                 : //
      43                 : // class MyClass {
      44                 : //  private:
      45                 : //   // This factory will be used to schedule invocations of SomeMethod.
      46                 : //   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
      47                 : //
      48                 : //  public:
      49                 : //   // It is safe to suppress warning 4355 here.
      50                 : //   MyClass() : some_method_factory_(this) { }
      51                 : //
      52                 : //   void SomeMethod() {
      53                 : //     // If this function might be called directly, you might want to revoke
      54                 : //     // any outstanding runnable methods scheduled to call it.  If it's not
      55                 : //     // referenced other than by the factory, this is unnecessary.
      56                 : //     some_method_factory_.RevokeAll();
      57                 : //     ...
      58                 : //   }
      59                 : //
      60                 : //   void ScheduleSomeMethod() {
      61                 : //     // If you'd like to only only have one pending task at a time, test for
      62                 : //     // |empty| before manufacturing another task.
      63                 : //     if (!some_method_factory_.empty())
      64                 : //       return;
      65                 : //
      66                 : //     // The factories are not thread safe, so always invoke on
      67                 : //     // |MessageLoop::current()|.
      68                 : //     MessageLoop::current()->PostDelayedTask(FROM_HERE,
      69                 : //         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
      70                 : //         kSomeMethodDelayMS);
      71                 : //   }
      72                 : // };
      73                 : 
      74                 : // A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from
      75                 : // running after it is destroyed.
      76                 : template<class TaskType>
      77                 : class ScopedTaskFactory : public RevocableStore {
      78                 :  public:
      79                 :   ScopedTaskFactory() { }
      80                 : 
      81                 :   // Create a new task.
      82                 :   inline TaskType* NewTask() {
      83                 :     return new TaskWrapper(this);
      84                 :   }
      85                 : 
      86               0 :   class TaskWrapper : public TaskType, public NonThreadSafe {
      87                 :    public:
      88               0 :     explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
      89                 : 
      90               0 :     virtual void Run() {
      91               0 :       if (!revocable_.revoked())
      92               0 :         TaskType::Run();
      93               0 :     }
      94                 : 
      95                 :    private:
      96                 :     Revocable revocable_;
      97                 : 
      98                 :     DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);
      99                 :   };
     100                 : 
     101                 :  private:
     102                 :   DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory);
     103                 : };
     104                 : 
     105                 : // A ScopedRunnableMethodFactory creates runnable methods for a specified
     106                 : // object.  This is particularly useful for generating callbacks for
     107                 : // non-reference counted objects when the factory is a member of the object.
     108                 : template<class T>
     109               0 : class ScopedRunnableMethodFactory : public RevocableStore {
     110                 :  public:
     111               1 :   explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }
     112                 : 
     113                 :   template <class Method>
     114               0 :   inline Task* NewRunnableMethod(Method method) {
     115                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     116                 :         Method, Tuple0> >::TaskWrapper TaskWrapper;
     117                 : 
     118               0 :     TaskWrapper* task = new TaskWrapper(this);
     119               0 :     task->Init(object_, method, MakeTuple());
     120               0 :     return task;
     121                 :   }
     122                 : 
     123                 :   template <class Method, class A>
     124                 :   inline Task* NewRunnableMethod(Method method, const A& a) {
     125                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     126                 :         Method, Tuple1<A> > >::TaskWrapper TaskWrapper;
     127                 : 
     128                 :     TaskWrapper* task = new TaskWrapper(this);
     129                 :     task->Init(object_, method, MakeTuple(a));
     130                 :     return task;
     131                 :   }
     132                 : 
     133                 :   template <class Method, class A, class B>
     134                 :   inline Task* NewRunnableMethod(Method method, const A& a, const B& b) {
     135                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     136                 :         Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper;
     137                 : 
     138                 :     TaskWrapper* task = new TaskWrapper(this);
     139                 :     task->Init(object_, method, MakeTuple(a, b));
     140                 :     return task;
     141                 :   }
     142                 : 
     143                 :   template <class Method, class A, class B, class C>
     144                 :   inline Task* NewRunnableMethod(Method method,
     145                 :                                  const A& a,
     146                 :                                  const B& b,
     147                 :                                  const C& c) {
     148                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     149                 :         Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper;
     150                 : 
     151                 :     TaskWrapper* task = new TaskWrapper(this);
     152                 :     task->Init(object_, method, MakeTuple(a, b, c));
     153                 :     return task;
     154                 :   }
     155                 : 
     156                 :   template <class Method, class A, class B, class C, class D>
     157                 :   inline Task* NewRunnableMethod(Method method,
     158                 :                                  const A& a,
     159                 :                                  const B& b,
     160                 :                                  const C& c,
     161                 :                                  const D& d) {
     162                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     163                 :         Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper;
     164                 : 
     165                 :     TaskWrapper* task = new TaskWrapper(this);
     166                 :     task->Init(object_, method, MakeTuple(a, b, c, d));
     167                 :     return task;
     168                 :   }
     169                 : 
     170                 :   template <class Method, class A, class B, class C, class D, class E>
     171                 :   inline Task* NewRunnableMethod(Method method,
     172                 :                                  const A& a,
     173                 :                                  const B& b,
     174                 :                                  const C& c,
     175                 :                                  const D& d,
     176                 :                                  const E& e) {
     177                 :     typedef typename ScopedTaskFactory<RunnableMethod<
     178                 :         Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper;
     179                 : 
     180                 :     TaskWrapper* task = new TaskWrapper(this);
     181                 :     task->Init(object_, method, MakeTuple(a, b, c, d, e));
     182                 :     return task;
     183                 :   }
     184                 : 
     185                 :  protected:
     186                 :   template <class Method, class Params>
     187               0 :   class RunnableMethod : public Task {
     188                 :    public:
     189               0 :     RunnableMethod() { }
     190                 : 
     191               0 :     void Init(T* obj, Method meth, const Params& params) {
     192               0 :       obj_ = obj;
     193               0 :       meth_ = meth;
     194                 :       params_ = params;
     195               0 :     }
     196                 : 
     197               0 :     virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
     198                 : 
     199                 :    private:
     200                 :     T* obj_;
     201                 :     Method meth_;
     202                 :     Params params_;
     203                 : 
     204                 :     DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);
     205                 :   };
     206                 : 
     207                 :  private:
     208                 :   T* object_;
     209                 : 
     210                 :   DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory);
     211                 : };
     212                 : 
     213                 : // General task implementations ------------------------------------------------
     214                 : 
     215                 : // Task to delete an object
     216                 : template<class T>
     217               0 : class DeleteTask : public CancelableTask {
     218                 :  public:
     219               0 :   explicit DeleteTask(T* obj) : obj_(obj) {
     220               0 :   }
     221               0 :   virtual void Run() {
     222               0 :     delete obj_;
     223               0 :   }
     224               0 :   virtual void Cancel() {
     225               0 :     obj_ = NULL;
     226               0 :   }
     227                 :  private:
     228                 :   T* obj_;
     229                 : };
     230                 : 
     231                 : // Task to Release() an object
     232                 : template<class T>
     233                 : class ReleaseTask : public CancelableTask {
     234                 :  public:
     235                 :   explicit ReleaseTask(T* obj) : obj_(obj) {
     236                 :   }
     237                 :   virtual void Run() {
     238                 :     if (obj_)
     239                 :       obj_->Release();
     240                 :   }
     241                 :   virtual void Cancel() {
     242                 :     obj_ = NULL;
     243                 :   }
     244                 :  private:
     245                 :   T* obj_;
     246                 : };
     247                 : 
     248                 : // RunnableMethodTraits --------------------------------------------------------
     249                 : //
     250                 : // This traits-class is used by RunnableMethod to manage the lifetime of the
     251                 : // callee object.  By default, it is assumed that the callee supports AddRef
     252                 : // and Release methods.  A particular class can specialize this template to
     253                 : // define other lifetime management.  For example, if the callee is known to
     254                 : // live longer than the RunnableMethod object, then a RunnableMethodTraits
     255                 : // struct could be defined with empty RetainCallee and ReleaseCallee methods.
     256                 : 
     257                 : template <class T>
     258               0 : struct RunnableMethodTraits {
     259               0 :   static void RetainCallee(T* obj) {
     260               0 :     obj->AddRef();
     261               0 :   }
     262               0 :   static void ReleaseCallee(T* obj) {
     263               0 :     obj->Release();
     264               0 :   }
     265                 : };
     266                 : 
     267                 : // RunnableMethod and RunnableFunction -----------------------------------------
     268                 : //
     269                 : // Runnable methods are a type of task that call a function on an object when
     270                 : // they are run. We implement both an object and a set of NewRunnableMethod and
     271                 : // NewRunnableFunction functions for convenience. These functions are
     272                 : // overloaded and will infer the template types, simplifying calling code.
     273                 : //
     274                 : // The template definitions all use the following names:
     275                 : // T                - the class type of the object you're supplying
     276                 : //                    this is not needed for the Static version of the call
     277                 : // Method/Function  - the signature of a pointer to the method or function you
     278                 : //                    want to call
     279                 : // Param            - the parameter(s) to the method, possibly packed as a Tuple
     280                 : // A                - the first parameter (if any) to the method
     281                 : // B                - the second parameter (if any) to the mathod
     282                 : //
     283                 : // Put these all together and you get an object that can call a method whose
     284                 : // signature is:
     285                 : //   R T::MyFunction([A[, B]])
     286                 : //
     287                 : // Usage:
     288                 : // PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])
     289                 : // PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
     290                 : 
     291                 : // RunnableMethod and NewRunnableMethod implementation -------------------------
     292                 : 
     293                 : template <class T, class Method, class Params>
     294                 : class RunnableMethod : public CancelableTask,
     295                 :                        public RunnableMethodTraits<T> {
     296                 :  public:
     297               1 :   RunnableMethod(T* obj, Method meth, const Params& params)
     298               1 :       : obj_(obj), meth_(meth), params_(params) {
     299               1 :     this->RetainCallee(obj_);
     300               1 :   }
     301               0 :   ~RunnableMethod() {
     302               0 :     ReleaseCallee();
     303               0 :   }
     304                 : 
     305               0 :   virtual void Run() {
     306               0 :     if (obj_)
     307               0 :       DispatchToMethod(obj_, meth_, params_);
     308               0 :   }
     309                 : 
     310               0 :   virtual void Cancel() {
     311               0 :     ReleaseCallee();
     312               0 :   }
     313                 : 
     314                 :  private:
     315               0 :   void ReleaseCallee() {
     316               0 :     if (obj_) {
     317               0 :       RunnableMethodTraits<T>::ReleaseCallee(obj_);
     318               0 :       obj_ = NULL;
     319                 :     }
     320               0 :   }
     321                 : 
     322                 :   T* obj_;
     323                 :   Method meth_;
     324                 :   Params params_;
     325                 : };
     326                 : 
     327                 : template <class T, class Method>
     328               1 : inline CancelableTask* NewRunnableMethod(T* object, Method method) {
     329               2 :   return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
     330                 : }
     331                 : 
     332                 : template <class T, class Method, class A>
     333               0 : inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
     334                 :   return new RunnableMethod<T, Method, Tuple1<A> >(object,
     335                 :                                                    method,
     336               0 :                                                    MakeTuple(a));
     337                 : }
     338                 : 
     339                 : template <class T, class Method, class A, class B>
     340               0 : inline CancelableTask* NewRunnableMethod(T* object, Method method,
     341                 : const A& a, const B& b) {
     342                 :   return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
     343               0 :                                                       MakeTuple(a, b));
     344                 : }
     345                 : 
     346                 : template <class T, class Method, class A, class B, class C>
     347               0 : inline CancelableTask* NewRunnableMethod(T* object, Method method,
     348                 :                                           const A& a, const B& b, const C& c) {
     349                 :   return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
     350               0 :                                                          MakeTuple(a, b, c));
     351                 : }
     352                 : 
     353                 : template <class T, class Method, class A, class B, class C, class D>
     354                 : inline CancelableTask* NewRunnableMethod(T* object, Method method,
     355                 :                                           const A& a, const B& b,
     356                 :                                           const C& c, const D& d) {
     357                 :   return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
     358                 :                                                             MakeTuple(a, b,
     359                 :                                                                       c, d));
     360                 : }
     361                 : 
     362                 : template <class T, class Method, class A, class B, class C, class D, class E>
     363                 : inline CancelableTask* NewRunnableMethod(T* object, Method method,
     364                 :                                           const A& a, const B& b,
     365                 :                                           const C& c, const D& d, const E& e) {
     366                 :   return new RunnableMethod<T,
     367                 :                             Method,
     368                 :                             Tuple5<A, B, C, D, E> >(object,
     369                 :                                                     method,
     370                 :                                                     MakeTuple(a, b, c, d, e));
     371                 : }
     372                 : 
     373                 : template <class T, class Method, class A, class B, class C, class D, class E,
     374                 :           class F>
     375                 : inline CancelableTask* NewRunnableMethod(T* object, Method method,
     376                 :                                           const A& a, const B& b,
     377                 :                                           const C& c, const D& d, const E& e,
     378                 :                                           const F& f) {
     379                 :   return new RunnableMethod<T,
     380                 :                             Method,
     381                 :                             Tuple6<A, B, C, D, E, F> >(object,
     382                 :                                                        method,
     383                 :                                                        MakeTuple(a, b, c, d, e,
     384                 :                                                                  f));
     385                 : }
     386                 : 
     387                 : template <class T, class Method, class A, class B, class C, class D, class E,
     388                 :           class F, class G>
     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                 :                                          const F& f, const G& g) {
     393                 :   return new RunnableMethod<T,
     394                 :                             Method,
     395                 :                             Tuple7<A, B, C, D, E, F, G> >(object,
     396                 :                                                           method,
     397                 :                                                           MakeTuple(a, b, c, d,
     398                 :                                                                     e, f, g));
     399                 : }
     400                 : 
     401                 : // RunnableFunction and NewRunnableFunction implementation ---------------------
     402                 : 
     403                 : template <class Function, class Params>
     404                 : class RunnableFunction : public CancelableTask {
     405                 :  public:
     406               0 :   RunnableFunction(Function function, const Params& params)
     407               0 :       : function_(function), params_(params) {
     408               0 :   }
     409                 : 
     410               0 :   ~RunnableFunction() {
     411               0 :   }
     412                 : 
     413               0 :   virtual void Run() {
     414               0 :     if (function_)
     415               0 :       DispatchToFunction(function_, params_);
     416               0 :   }
     417                 : 
     418               0 :   virtual void Cancel() {
     419               0 :   }
     420                 : 
     421                 :  private:
     422                 :   Function function_;
     423                 :   Params params_;
     424                 : };
     425                 : 
     426                 : template <class Function>
     427                 : inline CancelableTask* NewRunnableFunction(Function function) {
     428                 :   return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
     429                 : }
     430                 : 
     431                 : template <class Function, class A>
     432               0 : inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
     433               0 :   return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
     434                 : }
     435                 : 
     436                 : template <class Function, class A, class B>
     437                 : inline CancelableTask* NewRunnableFunction(Function function,
     438                 :                                            const A& a, const B& b) {
     439                 :   return new RunnableFunction<Function, Tuple2<A, B> >(function,
     440                 :                                                        MakeTuple(a, b));
     441                 : }
     442                 : 
     443                 : template <class Function, class A, class B, class C>
     444                 : inline CancelableTask* NewRunnableFunction(Function function,
     445                 :                                            const A& a, const B& b,
     446                 :                                            const C& c) {
     447                 :   return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
     448                 :                                                           MakeTuple(a, b, c));
     449                 : }
     450                 : 
     451                 : template <class Function, class A, class B, class C, class D>
     452                 : inline CancelableTask* NewRunnableFunction(Function function,
     453                 :                                            const A& a, const B& b,
     454                 :                                            const C& c, const D& d) {
     455                 :   return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
     456                 :                                                              MakeTuple(a, b,
     457                 :                                                                        c, d));
     458                 : }
     459                 : 
     460                 : template <class Function, class A, class B, class C, class D, class E>
     461                 : inline CancelableTask* NewRunnableFunction(Function function,
     462                 :                                            const A& a, const B& b,
     463                 :                                            const C& c, const D& d,
     464                 :                                            const E& e) {
     465                 :   return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
     466                 :                                                                 MakeTuple(a, b,
     467                 :                                                                           c, d,
     468                 :                                                                           e));
     469                 : }
     470                 : 
     471                 : // Callback --------------------------------------------------------------------
     472                 : //
     473                 : // A Callback is like a Task but with unbound parameters. It is basically an
     474                 : // object-oriented function pointer.
     475                 : //
     476                 : // Callbacks are designed to work with Tuples.  A set of helper functions and
     477                 : // classes is provided to hide the Tuple details from the consumer.  Client
     478                 : // code will generally work with the CallbackRunner base class, which merely
     479                 : // provides a Run method and is returned by the New* functions. This allows
     480                 : // users to not care which type of class implements the callback, only that it
     481                 : // has a certain number and type of arguments.
     482                 : //
     483                 : // The implementation of this is done by CallbackImpl, which inherits
     484                 : // CallbackStorage to store the data. This allows the storage of the data
     485                 : // (requiring the class type T) to be hidden from users, who will want to call
     486                 : // this regardless of the implementor's type T.
     487                 : //
     488                 : // Note that callbacks currently have no facility for cancelling or abandoning
     489                 : // them. We currently handle this at a higher level for cases where this is
     490                 : // necessary. The pointer in a callback must remain valid until the callback
     491                 : // is made.
     492                 : //
     493                 : // Like Task, the callback executor is responsible for deleting the callback
     494                 : // pointer once the callback has executed.
     495                 : //
     496                 : // Example client usage:
     497                 : //   void Object::DoStuff(int, string);
     498                 : //   Callback2<int, string>::Type* callback =
     499                 : //       NewCallback(obj, &Object::DoStuff);
     500                 : //   callback->Run(5, string("hello"));
     501                 : //   delete callback;
     502                 : // or, equivalently, using tuples directly:
     503                 : //   CallbackRunner<Tuple2<int, string> >* callback =
     504                 : //       NewCallback(obj, &Object::DoStuff);
     505                 : //   callback->RunWithParams(MakeTuple(5, string("hello")));
     506                 : 
     507                 : // Base for all Callbacks that handles storage of the pointers.
     508                 : template <class T, typename Method>
     509                 : class CallbackStorage {
     510                 :  public:
     511                 :   CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
     512                 :   }
     513                 : 
     514                 :  protected:
     515                 :   T* obj_;
     516                 :   Method meth_;
     517                 : };
     518                 : 
     519                 : // Interface that is exposed to the consumer, that does the actual calling
     520                 : // of the method.
     521                 : template <typename Params>
     522                 : class CallbackRunner {
     523                 :  public:
     524                 :   typedef Params TupleType;
     525                 : 
     526                 :   virtual ~CallbackRunner() {}
     527                 :   virtual void RunWithParams(const Params& params) = 0;
     528                 : 
     529                 :   // Convenience functions so callers don't have to deal with Tuples.
     530                 :   inline void Run() {
     531                 :     RunWithParams(Tuple0());
     532                 :   }
     533                 : 
     534                 :   template <typename Arg1>
     535                 :   inline void Run(const Arg1& a) {
     536                 :     RunWithParams(Params(a));
     537                 :   }
     538                 : 
     539                 :   template <typename Arg1, typename Arg2>
     540                 :   inline void Run(const Arg1& a, const Arg2& b) {
     541                 :     RunWithParams(Params(a, b));
     542                 :   }
     543                 : 
     544                 :   template <typename Arg1, typename Arg2, typename Arg3>
     545                 :   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
     546                 :     RunWithParams(Params(a, b, c));
     547                 :   }
     548                 : 
     549                 :   template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
     550                 :   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
     551                 :     RunWithParams(Params(a, b, c, d));
     552                 :   }
     553                 : 
     554                 :   template <typename Arg1, typename Arg2, typename Arg3,
     555                 :             typename Arg4, typename Arg5>
     556                 :   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
     557                 :                   const Arg4& d, const Arg5& e) {
     558                 :     RunWithParams(Params(a, b, c, d, e));
     559                 :   }
     560                 : };
     561                 : 
     562                 : template <class T, typename Method, typename Params>
     563                 : class CallbackImpl : public CallbackStorage<T, Method>,
     564                 :                      public CallbackRunner<Params> {
     565                 :  public:
     566                 :   CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
     567                 :   }
     568                 :   virtual void RunWithParams(const Params& params) {
     569                 :     // use "this->" to force C++ to look inside our templatized base class; see
     570                 :     // Effective C++, 3rd Ed, item 43, p210 for details.
     571                 :     DispatchToMethod(this->obj_, this->meth_, params);
     572                 :   }
     573                 : };
     574                 : 
     575                 : // 0-arg implementation
     576                 : struct Callback0 {
     577                 :   typedef CallbackRunner<Tuple0> Type;
     578                 : };
     579                 : 
     580                 : template <class T>
     581                 : typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
     582                 :   return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
     583                 : }
     584                 : 
     585                 : // 1-arg implementation
     586                 : template <typename Arg1>
     587                 : struct Callback1 {
     588                 :   typedef CallbackRunner<Tuple1<Arg1> > Type;
     589                 : };
     590                 : 
     591                 : template <class T, typename Arg1>
     592                 : typename Callback1<Arg1>::Type* NewCallback(T* object,
     593                 :                                             void (T::*method)(Arg1)) {
     594                 :   return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
     595                 : }
     596                 : 
     597                 : // 2-arg implementation
     598                 : template <typename Arg1, typename Arg2>
     599                 : struct Callback2 {
     600                 :   typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
     601                 : };
     602                 : 
     603                 : template <class T, typename Arg1, typename Arg2>
     604                 : typename Callback2<Arg1, Arg2>::Type* NewCallback(
     605                 :     T* object,
     606                 :     void (T::*method)(Arg1, Arg2)) {
     607                 :   return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
     608                 :       Tuple2<Arg1, Arg2> >(object, method);
     609                 : }
     610                 : 
     611                 : // 3-arg implementation
     612                 : template <typename Arg1, typename Arg2, typename Arg3>
     613                 : struct Callback3 {
     614                 :   typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
     615                 : };
     616                 : 
     617                 : template <class T, typename Arg1, typename Arg2, typename Arg3>
     618                 : typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
     619                 :     T* object,
     620                 :     void (T::*method)(Arg1, Arg2, Arg3)) {
     621                 :   return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
     622                 :       Tuple3<Arg1, Arg2, Arg3> >(object, method);
     623                 : }
     624                 : 
     625                 : // 4-arg implementation
     626                 : template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
     627                 : struct Callback4 {
     628                 :   typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
     629                 : };
     630                 : 
     631                 : template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
     632                 : typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
     633                 :     T* object,
     634                 :     void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
     635                 :   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
     636                 :       Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
     637                 : }
     638                 : 
     639                 : // 5-arg implementation
     640                 : template <typename Arg1, typename Arg2, typename Arg3,
     641                 :           typename Arg4, typename Arg5>
     642                 : struct Callback5 {
     643                 :   typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
     644                 : };
     645                 : 
     646                 : template <class T, typename Arg1, typename Arg2,
     647                 :           typename Arg3, typename Arg4, typename Arg5>
     648                 : typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
     649                 :     T* object,
     650                 :     void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
     651                 :   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
     652                 :       Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
     653                 : }
     654                 : 
     655                 : // An UnboundMethod is a wrapper for a method where the actual object is
     656                 : // provided at Run dispatch time.
     657                 : template <class T, class Method, class Params>
     658                 : class UnboundMethod {
     659                 :  public:
     660               0 :   UnboundMethod(Method m, Params p) : m_(m), p_(p) {}
     661               0 :   void Run(T* obj) const {
     662               0 :     DispatchToMethod(obj, m_, p_);
     663               0 :   }
     664                 :  private:
     665                 :   Method m_;
     666                 :   Params p_;
     667                 : };
     668                 : 
     669                 : #endif  // BASE_TASK_H_

Generated by: LCOV version 1.7