ipc/chromium/src/base/task.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
     5 #ifndef BASE_TASK_H_
     6 #define BASE_TASK_H_
     8 #include "base/non_thread_safe.h"
     9 #include "base/revocable_store.h"
    10 #include "base/tracked.h"
    11 #include "base/tuple.h"
    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.
    18 class Task : public tracked_objects::Tracked {
    19  public:
    20   Task() {}
    21   virtual ~Task() {}
    23   // Tasks are automatically deleted after Run is called.
    24   virtual void Run() = 0;
    25 };
    27 class CancelableTask : public Task {
    28  public:
    29   // Not all tasks support cancellation.
    30   virtual void Cancel() = 0;
    31 };
    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 // };
    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() { }
    81   // Create a new task.
    82   inline TaskType* NewTask() {
    83     return new TaskWrapper(this);
    84   }
    86   class TaskWrapper : public TaskType, public NonThreadSafe {
    87    public:
    88     explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
    90     virtual void Run() {
    91       if (!revocable_.revoked())
    92         TaskType::Run();
    93     }
    95    private:
    96     Revocable revocable_;
    98     DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);
    99   };
   101  private:
   102   DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory);
   103 };
   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 class ScopedRunnableMethodFactory : public RevocableStore {
   110  public:
   111   explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }
   113   template <class Method>
   114   inline Task* NewRunnableMethod(Method method) {
   115     typedef typename ScopedTaskFactory<RunnableMethod<
   116         Method, Tuple0> >::TaskWrapper TaskWrapper;
   118     TaskWrapper* task = new TaskWrapper(this);
   119     task->Init(object_, method, MakeTuple());
   120     return task;
   121   }
   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;
   128     TaskWrapper* task = new TaskWrapper(this);
   129     task->Init(object_, method, MakeTuple(a));
   130     return task;
   131   }
   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;
   138     TaskWrapper* task = new TaskWrapper(this);
   139     task->Init(object_, method, MakeTuple(a, b));
   140     return task;
   141   }
   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;
   151     TaskWrapper* task = new TaskWrapper(this);
   152     task->Init(object_, method, MakeTuple(a, b, c));
   153     return task;
   154   }
   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;
   165     TaskWrapper* task = new TaskWrapper(this);
   166     task->Init(object_, method, MakeTuple(a, b, c, d));
   167     return task;
   168   }
   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;
   180     TaskWrapper* task = new TaskWrapper(this);
   181     task->Init(object_, method, MakeTuple(a, b, c, d, e));
   182     return task;
   183   }
   185  protected:
   186   template <class Method, class Params>
   187   class RunnableMethod : public Task {
   188    public:
   189     RunnableMethod() { }
   191     void Init(T* obj, Method meth, const Params& params) {
   192       obj_ = obj;
   193       meth_ = meth;
   194       params_ = params;
   195     }
   197     virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
   199    private:
   200     T* obj_;
   201     Method meth_;
   202     Params params_;
   204     DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);
   205   };
   207  private:
   208   T* object_;
   210   DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory);
   211 };
   213 // General task implementations ------------------------------------------------
   215 // Task to delete an object
   216 template<class T>
   217 class DeleteTask : public CancelableTask {
   218  public:
   219   explicit DeleteTask(T* obj) : obj_(obj) {
   220   }
   221   virtual void Run() {
   222     delete obj_;
   223   }
   224   virtual void Cancel() {
   225     obj_ = NULL;
   226   }
   227  private:
   228   T* obj_;
   229 };
   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 };
   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.
   257 template <class T>
   258 struct RunnableMethodTraits {
   259   static void RetainCallee(T* obj) {
   260     obj->AddRef();
   261   }
   262   static void ReleaseCallee(T* obj) {
   263     obj->Release();
   264   }
   265 };
   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]])
   291 // RunnableMethod and NewRunnableMethod implementation -------------------------
   293 template <class T, class Method, class Params>
   294 class RunnableMethod : public CancelableTask,
   295                        public RunnableMethodTraits<T> {
   296  public:
   297   RunnableMethod(T* obj, Method meth, const Params& params)
   298       : obj_(obj), meth_(meth), params_(params) {
   299     this->RetainCallee(obj_);
   300   }
   301   ~RunnableMethod() {
   302     ReleaseCallee();
   303   }
   305   virtual void Run() {
   306     if (obj_)
   307       DispatchToMethod(obj_, meth_, params_);
   308   }
   310   virtual void Cancel() {
   311     ReleaseCallee();
   312   }
   314  private:
   315   void ReleaseCallee() {
   316     if (obj_) {
   317       RunnableMethodTraits<T>::ReleaseCallee(obj_);
   318       obj_ = NULL;
   319     }
   320   }
   322   T* obj_;
   323   Method meth_;
   324   Params params_;
   325 };
   327 template <class T, class Method>
   328 inline CancelableTask* NewRunnableMethod(T* object, Method method) {
   329   return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
   330 }
   332 template <class T, class Method, class A>
   333 inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
   334   return new RunnableMethod<T, Method, Tuple1<A> >(object,
   335                                                    method,
   336                                                    MakeTuple(a));
   337 }
   339 template <class T, class Method, class A, class B>
   340 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                                                       MakeTuple(a, b));
   344 }
   346 template <class T, class Method, class A, class B, class C>
   347 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                                                          MakeTuple(a, b, c));
   351 }
   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 }
   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 }
   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 }
   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 }
   401 // RunnableFunction and NewRunnableFunction implementation ---------------------
   403 template <class Function, class Params>
   404 class RunnableFunction : public CancelableTask {
   405  public:
   406   RunnableFunction(Function function, const Params& params)
   407       : function_(function), params_(params) {
   408   }
   410   ~RunnableFunction() {
   411   }
   413   virtual void Run() {
   414     if (function_)
   415       DispatchToFunction(function_, params_);
   416   }
   418   virtual void Cancel() {
   419     function_ = NULL;
   420   }
   422  private:
   423   Function function_;
   424   Params params_;
   425 };
   427 template <class Function>
   428 inline CancelableTask* NewRunnableFunction(Function function) {
   429   return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
   430 }
   432 template <class Function, class A>
   433 inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
   434   return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
   435 }
   437 template <class Function, class A, class B>
   438 inline CancelableTask* NewRunnableFunction(Function function,
   439                                            const A& a, const B& b) {
   440   return new RunnableFunction<Function, Tuple2<A, B> >(function,
   441                                                        MakeTuple(a, b));
   442 }
   444 template <class Function, class A, class B, class C>
   445 inline CancelableTask* NewRunnableFunction(Function function,
   446                                            const A& a, const B& b,
   447                                            const C& c) {
   448   return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
   449                                                           MakeTuple(a, b, c));
   450 }
   452 template <class Function, class A, class B, class C, class D>
   453 inline CancelableTask* NewRunnableFunction(Function function,
   454                                            const A& a, const B& b,
   455                                            const C& c, const D& d) {
   456   return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
   457                                                              MakeTuple(a, b,
   458                                                                        c, d));
   459 }
   461 template <class Function, class A, class B, class C, class D, class E>
   462 inline CancelableTask* NewRunnableFunction(Function function,
   463                                            const A& a, const B& b,
   464                                            const C& c, const D& d,
   465                                            const E& e) {
   466   return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
   467                                                                 MakeTuple(a, b,
   468                                                                           c, d,
   469                                                                           e));
   470 }
   472 // Callback --------------------------------------------------------------------
   473 //
   474 // A Callback is like a Task but with unbound parameters. It is basically an
   475 // object-oriented function pointer.
   476 //
   477 // Callbacks are designed to work with Tuples.  A set of helper functions and
   478 // classes is provided to hide the Tuple details from the consumer.  Client
   479 // code will generally work with the CallbackRunner base class, which merely
   480 // provides a Run method and is returned by the New* functions. This allows
   481 // users to not care which type of class implements the callback, only that it
   482 // has a certain number and type of arguments.
   483 //
   484 // The implementation of this is done by CallbackImpl, which inherits
   485 // CallbackStorage to store the data. This allows the storage of the data
   486 // (requiring the class type T) to be hidden from users, who will want to call
   487 // this regardless of the implementor's type T.
   488 //
   489 // Note that callbacks currently have no facility for cancelling or abandoning
   490 // them. We currently handle this at a higher level for cases where this is
   491 // necessary. The pointer in a callback must remain valid until the callback
   492 // is made.
   493 //
   494 // Like Task, the callback executor is responsible for deleting the callback
   495 // pointer once the callback has executed.
   496 //
   497 // Example client usage:
   498 //   void Object::DoStuff(int, string);
   499 //   Callback2<int, string>::Type* callback =
   500 //       NewCallback(obj, &Object::DoStuff);
   501 //   callback->Run(5, string("hello"));
   502 //   delete callback;
   503 // or, equivalently, using tuples directly:
   504 //   CallbackRunner<Tuple2<int, string> >* callback =
   505 //       NewCallback(obj, &Object::DoStuff);
   506 //   callback->RunWithParams(MakeTuple(5, string("hello")));
   508 // Base for all Callbacks that handles storage of the pointers.
   509 template <class T, typename Method>
   510 class CallbackStorage {
   511  public:
   512   CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
   513   }
   515  protected:
   516   T* obj_;
   517   Method meth_;
   518 };
   520 // Interface that is exposed to the consumer, that does the actual calling
   521 // of the method.
   522 template <typename Params>
   523 class CallbackRunner {
   524  public:
   525   typedef Params TupleType;
   527   virtual ~CallbackRunner() {}
   528   virtual void RunWithParams(const Params& params) = 0;
   530   // Convenience functions so callers don't have to deal with Tuples.
   531   inline void Run() {
   532     RunWithParams(Tuple0());
   533   }
   535   template <typename Arg1>
   536   inline void Run(const Arg1& a) {
   537     RunWithParams(Params(a));
   538   }
   540   template <typename Arg1, typename Arg2>
   541   inline void Run(const Arg1& a, const Arg2& b) {
   542     RunWithParams(Params(a, b));
   543   }
   545   template <typename Arg1, typename Arg2, typename Arg3>
   546   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
   547     RunWithParams(Params(a, b, c));
   548   }
   550   template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   551   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
   552     RunWithParams(Params(a, b, c, d));
   553   }
   555   template <typename Arg1, typename Arg2, typename Arg3,
   556             typename Arg4, typename Arg5>
   557   inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
   558                   const Arg4& d, const Arg5& e) {
   559     RunWithParams(Params(a, b, c, d, e));
   560   }
   561 };
   563 template <class T, typename Method, typename Params>
   564 class CallbackImpl : public CallbackStorage<T, Method>,
   565                      public CallbackRunner<Params> {
   566  public:
   567   CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
   568   }
   569   virtual void RunWithParams(const Params& params) {
   570     // use "this->" to force C++ to look inside our templatized base class; see
   571     // Effective C++, 3rd Ed, item 43, p210 for details.
   572     DispatchToMethod(this->obj_, this->meth_, params);
   573   }
   574 };
   576 // 0-arg implementation
   577 struct Callback0 {
   578   typedef CallbackRunner<Tuple0> Type;
   579 };
   581 template <class T>
   582 typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
   583   return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
   584 }
   586 // 1-arg implementation
   587 template <typename Arg1>
   588 struct Callback1 {
   589   typedef CallbackRunner<Tuple1<Arg1> > Type;
   590 };
   592 template <class T, typename Arg1>
   593 typename Callback1<Arg1>::Type* NewCallback(T* object,
   594                                             void (T::*method)(Arg1)) {
   595   return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
   596 }
   598 // 2-arg implementation
   599 template <typename Arg1, typename Arg2>
   600 struct Callback2 {
   601   typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
   602 };
   604 template <class T, typename Arg1, typename Arg2>
   605 typename Callback2<Arg1, Arg2>::Type* NewCallback(
   606     T* object,
   607     void (T::*method)(Arg1, Arg2)) {
   608   return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
   609       Tuple2<Arg1, Arg2> >(object, method);
   610 }
   612 // 3-arg implementation
   613 template <typename Arg1, typename Arg2, typename Arg3>
   614 struct Callback3 {
   615   typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
   616 };
   618 template <class T, typename Arg1, typename Arg2, typename Arg3>
   619 typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
   620     T* object,
   621     void (T::*method)(Arg1, Arg2, Arg3)) {
   622   return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
   623       Tuple3<Arg1, Arg2, Arg3> >(object, method);
   624 }
   626 // 4-arg implementation
   627 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   628 struct Callback4 {
   629   typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
   630 };
   632 template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   633 typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
   634     T* object,
   635     void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
   636   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
   637       Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
   638 }
   640 // 5-arg implementation
   641 template <typename Arg1, typename Arg2, typename Arg3,
   642           typename Arg4, typename Arg5>
   643 struct Callback5 {
   644   typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
   645 };
   647 template <class T, typename Arg1, typename Arg2,
   648           typename Arg3, typename Arg4, typename Arg5>
   649 typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
   650     T* object,
   651     void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
   652   return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
   653       Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
   654 }
   656 // An UnboundMethod is a wrapper for a method where the actual object is
   657 // provided at Run dispatch time.
   658 template <class T, class Method, class Params>
   659 class UnboundMethod {
   660  public:
   661   UnboundMethod(Method m, Params p) : m_(m), p_(p) {}
   662   void Run(T* obj) const {
   663     DispatchToMethod(obj, m_, p_);
   664   }
   665  private:
   666   Method m_;
   667   Params p_;
   668 };
   670 #endif  // BASE_TASK_H_

mercurial