ipc/chromium/src/base/task.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/task.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,670 @@
     1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#ifndef BASE_TASK_H_
     1.9 +#define BASE_TASK_H_
    1.10 +
    1.11 +#include "base/non_thread_safe.h"
    1.12 +#include "base/revocable_store.h"
    1.13 +#include "base/tracked.h"
    1.14 +#include "base/tuple.h"
    1.15 +
    1.16 +// Task ------------------------------------------------------------------------
    1.17 +//
    1.18 +// A task is a generic runnable thingy, usually used for running code on a
    1.19 +// different thread or for scheduling future tasks off of the message loop.
    1.20 +
    1.21 +class Task : public tracked_objects::Tracked {
    1.22 + public:
    1.23 +  Task() {}
    1.24 +  virtual ~Task() {}
    1.25 +
    1.26 +  // Tasks are automatically deleted after Run is called.
    1.27 +  virtual void Run() = 0;
    1.28 +};
    1.29 +
    1.30 +class CancelableTask : public Task {
    1.31 + public:
    1.32 +  // Not all tasks support cancellation.
    1.33 +  virtual void Cancel() = 0;
    1.34 +};
    1.35 +
    1.36 +// Scoped Factories ------------------------------------------------------------
    1.37 +//
    1.38 +// These scoped factory objects can be used by non-refcounted objects to safely
    1.39 +// place tasks in a message loop.  Each factory guarantees that the tasks it
    1.40 +// produces will not run after the factory is destroyed.  Commonly, factories
    1.41 +// are declared as class members, so the class' tasks will automatically cancel
    1.42 +// when the class instance is destroyed.
    1.43 +//
    1.44 +// Exampe Usage:
    1.45 +//
    1.46 +// class MyClass {
    1.47 +//  private:
    1.48 +//   // This factory will be used to schedule invocations of SomeMethod.
    1.49 +//   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
    1.50 +//
    1.51 +//  public:
    1.52 +//   // It is safe to suppress warning 4355 here.
    1.53 +//   MyClass() : some_method_factory_(this) { }
    1.54 +//
    1.55 +//   void SomeMethod() {
    1.56 +//     // If this function might be called directly, you might want to revoke
    1.57 +//     // any outstanding runnable methods scheduled to call it.  If it's not
    1.58 +//     // referenced other than by the factory, this is unnecessary.
    1.59 +//     some_method_factory_.RevokeAll();
    1.60 +//     ...
    1.61 +//   }
    1.62 +//
    1.63 +//   void ScheduleSomeMethod() {
    1.64 +//     // If you'd like to only only have one pending task at a time, test for
    1.65 +//     // |empty| before manufacturing another task.
    1.66 +//     if (!some_method_factory_.empty())
    1.67 +//       return;
    1.68 +//
    1.69 +//     // The factories are not thread safe, so always invoke on
    1.70 +//     // |MessageLoop::current()|.
    1.71 +//     MessageLoop::current()->PostDelayedTask(FROM_HERE,
    1.72 +//         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
    1.73 +//         kSomeMethodDelayMS);
    1.74 +//   }
    1.75 +// };
    1.76 +
    1.77 +// A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from
    1.78 +// running after it is destroyed.
    1.79 +template<class TaskType>
    1.80 +class ScopedTaskFactory : public RevocableStore {
    1.81 + public:
    1.82 +  ScopedTaskFactory() { }
    1.83 +
    1.84 +  // Create a new task.
    1.85 +  inline TaskType* NewTask() {
    1.86 +    return new TaskWrapper(this);
    1.87 +  }
    1.88 +
    1.89 +  class TaskWrapper : public TaskType, public NonThreadSafe {
    1.90 +   public:
    1.91 +    explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
    1.92 +
    1.93 +    virtual void Run() {
    1.94 +      if (!revocable_.revoked())
    1.95 +        TaskType::Run();
    1.96 +    }
    1.97 +
    1.98 +   private:
    1.99 +    Revocable revocable_;
   1.100 +
   1.101 +    DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);
   1.102 +  };
   1.103 +
   1.104 + private:
   1.105 +  DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory);
   1.106 +};
   1.107 +
   1.108 +// A ScopedRunnableMethodFactory creates runnable methods for a specified
   1.109 +// object.  This is particularly useful for generating callbacks for
   1.110 +// non-reference counted objects when the factory is a member of the object.
   1.111 +template<class T>
   1.112 +class ScopedRunnableMethodFactory : public RevocableStore {
   1.113 + public:
   1.114 +  explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }
   1.115 +
   1.116 +  template <class Method>
   1.117 +  inline Task* NewRunnableMethod(Method method) {
   1.118 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.119 +        Method, Tuple0> >::TaskWrapper TaskWrapper;
   1.120 +
   1.121 +    TaskWrapper* task = new TaskWrapper(this);
   1.122 +    task->Init(object_, method, MakeTuple());
   1.123 +    return task;
   1.124 +  }
   1.125 +
   1.126 +  template <class Method, class A>
   1.127 +  inline Task* NewRunnableMethod(Method method, const A& a) {
   1.128 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.129 +        Method, Tuple1<A> > >::TaskWrapper TaskWrapper;
   1.130 +
   1.131 +    TaskWrapper* task = new TaskWrapper(this);
   1.132 +    task->Init(object_, method, MakeTuple(a));
   1.133 +    return task;
   1.134 +  }
   1.135 +
   1.136 +  template <class Method, class A, class B>
   1.137 +  inline Task* NewRunnableMethod(Method method, const A& a, const B& b) {
   1.138 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.139 +        Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper;
   1.140 +
   1.141 +    TaskWrapper* task = new TaskWrapper(this);
   1.142 +    task->Init(object_, method, MakeTuple(a, b));
   1.143 +    return task;
   1.144 +  }
   1.145 +
   1.146 +  template <class Method, class A, class B, class C>
   1.147 +  inline Task* NewRunnableMethod(Method method,
   1.148 +                                 const A& a,
   1.149 +                                 const B& b,
   1.150 +                                 const C& c) {
   1.151 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.152 +        Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper;
   1.153 +
   1.154 +    TaskWrapper* task = new TaskWrapper(this);
   1.155 +    task->Init(object_, method, MakeTuple(a, b, c));
   1.156 +    return task;
   1.157 +  }
   1.158 +
   1.159 +  template <class Method, class A, class B, class C, class D>
   1.160 +  inline Task* NewRunnableMethod(Method method,
   1.161 +                                 const A& a,
   1.162 +                                 const B& b,
   1.163 +                                 const C& c,
   1.164 +                                 const D& d) {
   1.165 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.166 +        Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper;
   1.167 +
   1.168 +    TaskWrapper* task = new TaskWrapper(this);
   1.169 +    task->Init(object_, method, MakeTuple(a, b, c, d));
   1.170 +    return task;
   1.171 +  }
   1.172 +
   1.173 +  template <class Method, class A, class B, class C, class D, class E>
   1.174 +  inline Task* NewRunnableMethod(Method method,
   1.175 +                                 const A& a,
   1.176 +                                 const B& b,
   1.177 +                                 const C& c,
   1.178 +                                 const D& d,
   1.179 +                                 const E& e) {
   1.180 +    typedef typename ScopedTaskFactory<RunnableMethod<
   1.181 +        Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper;
   1.182 +
   1.183 +    TaskWrapper* task = new TaskWrapper(this);
   1.184 +    task->Init(object_, method, MakeTuple(a, b, c, d, e));
   1.185 +    return task;
   1.186 +  }
   1.187 +
   1.188 + protected:
   1.189 +  template <class Method, class Params>
   1.190 +  class RunnableMethod : public Task {
   1.191 +   public:
   1.192 +    RunnableMethod() { }
   1.193 +
   1.194 +    void Init(T* obj, Method meth, const Params& params) {
   1.195 +      obj_ = obj;
   1.196 +      meth_ = meth;
   1.197 +      params_ = params;
   1.198 +    }
   1.199 +
   1.200 +    virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
   1.201 +
   1.202 +   private:
   1.203 +    T* obj_;
   1.204 +    Method meth_;
   1.205 +    Params params_;
   1.206 +
   1.207 +    DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);
   1.208 +  };
   1.209 +
   1.210 + private:
   1.211 +  T* object_;
   1.212 +
   1.213 +  DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory);
   1.214 +};
   1.215 +
   1.216 +// General task implementations ------------------------------------------------
   1.217 +
   1.218 +// Task to delete an object
   1.219 +template<class T>
   1.220 +class DeleteTask : public CancelableTask {
   1.221 + public:
   1.222 +  explicit DeleteTask(T* obj) : obj_(obj) {
   1.223 +  }
   1.224 +  virtual void Run() {
   1.225 +    delete obj_;
   1.226 +  }
   1.227 +  virtual void Cancel() {
   1.228 +    obj_ = NULL;
   1.229 +  }
   1.230 + private:
   1.231 +  T* obj_;
   1.232 +};
   1.233 +
   1.234 +// Task to Release() an object
   1.235 +template<class T>
   1.236 +class ReleaseTask : public CancelableTask {
   1.237 + public:
   1.238 +  explicit ReleaseTask(T* obj) : obj_(obj) {
   1.239 +  }
   1.240 +  virtual void Run() {
   1.241 +    if (obj_)
   1.242 +      obj_->Release();
   1.243 +  }
   1.244 +  virtual void Cancel() {
   1.245 +    obj_ = NULL;
   1.246 +  }
   1.247 + private:
   1.248 +  T* obj_;
   1.249 +};
   1.250 +
   1.251 +// RunnableMethodTraits --------------------------------------------------------
   1.252 +//
   1.253 +// This traits-class is used by RunnableMethod to manage the lifetime of the
   1.254 +// callee object.  By default, it is assumed that the callee supports AddRef
   1.255 +// and Release methods.  A particular class can specialize this template to
   1.256 +// define other lifetime management.  For example, if the callee is known to
   1.257 +// live longer than the RunnableMethod object, then a RunnableMethodTraits
   1.258 +// struct could be defined with empty RetainCallee and ReleaseCallee methods.
   1.259 +
   1.260 +template <class T>
   1.261 +struct RunnableMethodTraits {
   1.262 +  static void RetainCallee(T* obj) {
   1.263 +    obj->AddRef();
   1.264 +  }
   1.265 +  static void ReleaseCallee(T* obj) {
   1.266 +    obj->Release();
   1.267 +  }
   1.268 +};
   1.269 +
   1.270 +// RunnableMethod and RunnableFunction -----------------------------------------
   1.271 +//
   1.272 +// Runnable methods are a type of task that call a function on an object when
   1.273 +// they are run. We implement both an object and a set of NewRunnableMethod and
   1.274 +// NewRunnableFunction functions for convenience. These functions are
   1.275 +// overloaded and will infer the template types, simplifying calling code.
   1.276 +//
   1.277 +// The template definitions all use the following names:
   1.278 +// T                - the class type of the object you're supplying
   1.279 +//                    this is not needed for the Static version of the call
   1.280 +// Method/Function  - the signature of a pointer to the method or function you
   1.281 +//                    want to call
   1.282 +// Param            - the parameter(s) to the method, possibly packed as a Tuple
   1.283 +// A                - the first parameter (if any) to the method
   1.284 +// B                - the second parameter (if any) to the mathod
   1.285 +//
   1.286 +// Put these all together and you get an object that can call a method whose
   1.287 +// signature is:
   1.288 +//   R T::MyFunction([A[, B]])
   1.289 +//
   1.290 +// Usage:
   1.291 +// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])
   1.292 +// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
   1.293 +
   1.294 +// RunnableMethod and NewRunnableMethod implementation -------------------------
   1.295 +
   1.296 +template <class T, class Method, class Params>
   1.297 +class RunnableMethod : public CancelableTask,
   1.298 +                       public RunnableMethodTraits<T> {
   1.299 + public:
   1.300 +  RunnableMethod(T* obj, Method meth, const Params& params)
   1.301 +      : obj_(obj), meth_(meth), params_(params) {
   1.302 +    this->RetainCallee(obj_);
   1.303 +  }
   1.304 +  ~RunnableMethod() {
   1.305 +    ReleaseCallee();
   1.306 +  }
   1.307 +
   1.308 +  virtual void Run() {
   1.309 +    if (obj_)
   1.310 +      DispatchToMethod(obj_, meth_, params_);
   1.311 +  }
   1.312 +
   1.313 +  virtual void Cancel() {
   1.314 +    ReleaseCallee();
   1.315 +  }
   1.316 +
   1.317 + private:
   1.318 +  void ReleaseCallee() {
   1.319 +    if (obj_) {
   1.320 +      RunnableMethodTraits<T>::ReleaseCallee(obj_);
   1.321 +      obj_ = NULL;
   1.322 +    }
   1.323 +  }
   1.324 +
   1.325 +  T* obj_;
   1.326 +  Method meth_;
   1.327 +  Params params_;
   1.328 +};
   1.329 +
   1.330 +template <class T, class Method>
   1.331 +inline CancelableTask* NewRunnableMethod(T* object, Method method) {
   1.332 +  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
   1.333 +}
   1.334 +
   1.335 +template <class T, class Method, class A>
   1.336 +inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
   1.337 +  return new RunnableMethod<T, Method, Tuple1<A> >(object,
   1.338 +                                                   method,
   1.339 +                                                   MakeTuple(a));
   1.340 +}
   1.341 +
   1.342 +template <class T, class Method, class A, class B>
   1.343 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.344 +const A& a, const B& b) {
   1.345 +  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
   1.346 +                                                      MakeTuple(a, b));
   1.347 +}
   1.348 +
   1.349 +template <class T, class Method, class A, class B, class C>
   1.350 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.351 +                                          const A& a, const B& b, const C& c) {
   1.352 +  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
   1.353 +                                                         MakeTuple(a, b, c));
   1.354 +}
   1.355 +
   1.356 +template <class T, class Method, class A, class B, class C, class D>
   1.357 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.358 +                                          const A& a, const B& b,
   1.359 +                                          const C& c, const D& d) {
   1.360 +  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
   1.361 +                                                            MakeTuple(a, b,
   1.362 +                                                                      c, d));
   1.363 +}
   1.364 +
   1.365 +template <class T, class Method, class A, class B, class C, class D, class E>
   1.366 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.367 +                                          const A& a, const B& b,
   1.368 +                                          const C& c, const D& d, const E& e) {
   1.369 +  return new RunnableMethod<T,
   1.370 +                            Method,
   1.371 +                            Tuple5<A, B, C, D, E> >(object,
   1.372 +                                                    method,
   1.373 +                                                    MakeTuple(a, b, c, d, e));
   1.374 +}
   1.375 +
   1.376 +template <class T, class Method, class A, class B, class C, class D, class E,
   1.377 +          class F>
   1.378 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.379 +                                          const A& a, const B& b,
   1.380 +                                          const C& c, const D& d, const E& e,
   1.381 +                                          const F& f) {
   1.382 +  return new RunnableMethod<T,
   1.383 +                            Method,
   1.384 +                            Tuple6<A, B, C, D, E, F> >(object,
   1.385 +                                                       method,
   1.386 +                                                       MakeTuple(a, b, c, d, e,
   1.387 +                                                                 f));
   1.388 +}
   1.389 +
   1.390 +template <class T, class Method, class A, class B, class C, class D, class E,
   1.391 +          class F, class G>
   1.392 +inline CancelableTask* NewRunnableMethod(T* object, Method method,
   1.393 +                                         const A& a, const B& b,
   1.394 +                                         const C& c, const D& d, const E& e,
   1.395 +                                         const F& f, const G& g) {
   1.396 +  return new RunnableMethod<T,
   1.397 +                            Method,
   1.398 +                            Tuple7<A, B, C, D, E, F, G> >(object,
   1.399 +                                                          method,
   1.400 +                                                          MakeTuple(a, b, c, d,
   1.401 +                                                                    e, f, g));
   1.402 +}
   1.403 +
   1.404 +// RunnableFunction and NewRunnableFunction implementation ---------------------
   1.405 +
   1.406 +template <class Function, class Params>
   1.407 +class RunnableFunction : public CancelableTask {
   1.408 + public:
   1.409 +  RunnableFunction(Function function, const Params& params)
   1.410 +      : function_(function), params_(params) {
   1.411 +  }
   1.412 +
   1.413 +  ~RunnableFunction() {
   1.414 +  }
   1.415 +
   1.416 +  virtual void Run() {
   1.417 +    if (function_)
   1.418 +      DispatchToFunction(function_, params_);
   1.419 +  }
   1.420 +
   1.421 +  virtual void Cancel() {
   1.422 +    function_ = NULL;
   1.423 +  }
   1.424 +
   1.425 + private:
   1.426 +  Function function_;
   1.427 +  Params params_;
   1.428 +};
   1.429 +
   1.430 +template <class Function>
   1.431 +inline CancelableTask* NewRunnableFunction(Function function) {
   1.432 +  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
   1.433 +}
   1.434 +
   1.435 +template <class Function, class A>
   1.436 +inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
   1.437 +  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
   1.438 +}
   1.439 +
   1.440 +template <class Function, class A, class B>
   1.441 +inline CancelableTask* NewRunnableFunction(Function function,
   1.442 +                                           const A& a, const B& b) {
   1.443 +  return new RunnableFunction<Function, Tuple2<A, B> >(function,
   1.444 +                                                       MakeTuple(a, b));
   1.445 +}
   1.446 +
   1.447 +template <class Function, class A, class B, class C>
   1.448 +inline CancelableTask* NewRunnableFunction(Function function,
   1.449 +                                           const A& a, const B& b,
   1.450 +                                           const C& c) {
   1.451 +  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
   1.452 +                                                          MakeTuple(a, b, c));
   1.453 +}
   1.454 +
   1.455 +template <class Function, class A, class B, class C, class D>
   1.456 +inline CancelableTask* NewRunnableFunction(Function function,
   1.457 +                                           const A& a, const B& b,
   1.458 +                                           const C& c, const D& d) {
   1.459 +  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
   1.460 +                                                             MakeTuple(a, b,
   1.461 +                                                                       c, d));
   1.462 +}
   1.463 +
   1.464 +template <class Function, class A, class B, class C, class D, class E>
   1.465 +inline CancelableTask* NewRunnableFunction(Function function,
   1.466 +                                           const A& a, const B& b,
   1.467 +                                           const C& c, const D& d,
   1.468 +                                           const E& e) {
   1.469 +  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
   1.470 +                                                                MakeTuple(a, b,
   1.471 +                                                                          c, d,
   1.472 +                                                                          e));
   1.473 +}
   1.474 +
   1.475 +// Callback --------------------------------------------------------------------
   1.476 +//
   1.477 +// A Callback is like a Task but with unbound parameters. It is basically an
   1.478 +// object-oriented function pointer.
   1.479 +//
   1.480 +// Callbacks are designed to work with Tuples.  A set of helper functions and
   1.481 +// classes is provided to hide the Tuple details from the consumer.  Client
   1.482 +// code will generally work with the CallbackRunner base class, which merely
   1.483 +// provides a Run method and is returned by the New* functions. This allows
   1.484 +// users to not care which type of class implements the callback, only that it
   1.485 +// has a certain number and type of arguments.
   1.486 +//
   1.487 +// The implementation of this is done by CallbackImpl, which inherits
   1.488 +// CallbackStorage to store the data. This allows the storage of the data
   1.489 +// (requiring the class type T) to be hidden from users, who will want to call
   1.490 +// this regardless of the implementor's type T.
   1.491 +//
   1.492 +// Note that callbacks currently have no facility for cancelling or abandoning
   1.493 +// them. We currently handle this at a higher level for cases where this is
   1.494 +// necessary. The pointer in a callback must remain valid until the callback
   1.495 +// is made.
   1.496 +//
   1.497 +// Like Task, the callback executor is responsible for deleting the callback
   1.498 +// pointer once the callback has executed.
   1.499 +//
   1.500 +// Example client usage:
   1.501 +//   void Object::DoStuff(int, string);
   1.502 +//   Callback2<int, string>::Type* callback =
   1.503 +//       NewCallback(obj, &Object::DoStuff);
   1.504 +//   callback->Run(5, string("hello"));
   1.505 +//   delete callback;
   1.506 +// or, equivalently, using tuples directly:
   1.507 +//   CallbackRunner<Tuple2<int, string> >* callback =
   1.508 +//       NewCallback(obj, &Object::DoStuff);
   1.509 +//   callback->RunWithParams(MakeTuple(5, string("hello")));
   1.510 +
   1.511 +// Base for all Callbacks that handles storage of the pointers.
   1.512 +template <class T, typename Method>
   1.513 +class CallbackStorage {
   1.514 + public:
   1.515 +  CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
   1.516 +  }
   1.517 +
   1.518 + protected:
   1.519 +  T* obj_;
   1.520 +  Method meth_;
   1.521 +};
   1.522 +
   1.523 +// Interface that is exposed to the consumer, that does the actual calling
   1.524 +// of the method.
   1.525 +template <typename Params>
   1.526 +class CallbackRunner {
   1.527 + public:
   1.528 +  typedef Params TupleType;
   1.529 +
   1.530 +  virtual ~CallbackRunner() {}
   1.531 +  virtual void RunWithParams(const Params& params) = 0;
   1.532 +
   1.533 +  // Convenience functions so callers don't have to deal with Tuples.
   1.534 +  inline void Run() {
   1.535 +    RunWithParams(Tuple0());
   1.536 +  }
   1.537 +
   1.538 +  template <typename Arg1>
   1.539 +  inline void Run(const Arg1& a) {
   1.540 +    RunWithParams(Params(a));
   1.541 +  }
   1.542 +
   1.543 +  template <typename Arg1, typename Arg2>
   1.544 +  inline void Run(const Arg1& a, const Arg2& b) {
   1.545 +    RunWithParams(Params(a, b));
   1.546 +  }
   1.547 +
   1.548 +  template <typename Arg1, typename Arg2, typename Arg3>
   1.549 +  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
   1.550 +    RunWithParams(Params(a, b, c));
   1.551 +  }
   1.552 +
   1.553 +  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   1.554 +  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
   1.555 +    RunWithParams(Params(a, b, c, d));
   1.556 +  }
   1.557 +
   1.558 +  template <typename Arg1, typename Arg2, typename Arg3,
   1.559 +            typename Arg4, typename Arg5>
   1.560 +  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
   1.561 +                  const Arg4& d, const Arg5& e) {
   1.562 +    RunWithParams(Params(a, b, c, d, e));
   1.563 +  }
   1.564 +};
   1.565 +
   1.566 +template <class T, typename Method, typename Params>
   1.567 +class CallbackImpl : public CallbackStorage<T, Method>,
   1.568 +                     public CallbackRunner<Params> {
   1.569 + public:
   1.570 +  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
   1.571 +  }
   1.572 +  virtual void RunWithParams(const Params& params) {
   1.573 +    // use "this->" to force C++ to look inside our templatized base class; see
   1.574 +    // Effective C++, 3rd Ed, item 43, p210 for details.
   1.575 +    DispatchToMethod(this->obj_, this->meth_, params);
   1.576 +  }
   1.577 +};
   1.578 +
   1.579 +// 0-arg implementation
   1.580 +struct Callback0 {
   1.581 +  typedef CallbackRunner<Tuple0> Type;
   1.582 +};
   1.583 +
   1.584 +template <class T>
   1.585 +typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
   1.586 +  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
   1.587 +}
   1.588 +
   1.589 +// 1-arg implementation
   1.590 +template <typename Arg1>
   1.591 +struct Callback1 {
   1.592 +  typedef CallbackRunner<Tuple1<Arg1> > Type;
   1.593 +};
   1.594 +
   1.595 +template <class T, typename Arg1>
   1.596 +typename Callback1<Arg1>::Type* NewCallback(T* object,
   1.597 +                                            void (T::*method)(Arg1)) {
   1.598 +  return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
   1.599 +}
   1.600 +
   1.601 +// 2-arg implementation
   1.602 +template <typename Arg1, typename Arg2>
   1.603 +struct Callback2 {
   1.604 +  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
   1.605 +};
   1.606 +
   1.607 +template <class T, typename Arg1, typename Arg2>
   1.608 +typename Callback2<Arg1, Arg2>::Type* NewCallback(
   1.609 +    T* object,
   1.610 +    void (T::*method)(Arg1, Arg2)) {
   1.611 +  return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
   1.612 +      Tuple2<Arg1, Arg2> >(object, method);
   1.613 +}
   1.614 +
   1.615 +// 3-arg implementation
   1.616 +template <typename Arg1, typename Arg2, typename Arg3>
   1.617 +struct Callback3 {
   1.618 +  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
   1.619 +};
   1.620 +
   1.621 +template <class T, typename Arg1, typename Arg2, typename Arg3>
   1.622 +typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
   1.623 +    T* object,
   1.624 +    void (T::*method)(Arg1, Arg2, Arg3)) {
   1.625 +  return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
   1.626 +      Tuple3<Arg1, Arg2, Arg3> >(object, method);
   1.627 +}
   1.628 +
   1.629 +// 4-arg implementation
   1.630 +template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   1.631 +struct Callback4 {
   1.632 +  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
   1.633 +};
   1.634 +
   1.635 +template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
   1.636 +typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
   1.637 +    T* object,
   1.638 +    void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
   1.639 +  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
   1.640 +      Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
   1.641 +}
   1.642 +
   1.643 +// 5-arg implementation
   1.644 +template <typename Arg1, typename Arg2, typename Arg3,
   1.645 +          typename Arg4, typename Arg5>
   1.646 +struct Callback5 {
   1.647 +  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
   1.648 +};
   1.649 +
   1.650 +template <class T, typename Arg1, typename Arg2,
   1.651 +          typename Arg3, typename Arg4, typename Arg5>
   1.652 +typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
   1.653 +    T* object,
   1.654 +    void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
   1.655 +  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
   1.656 +      Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
   1.657 +}
   1.658 +
   1.659 +// An UnboundMethod is a wrapper for a method where the actual object is
   1.660 +// provided at Run dispatch time.
   1.661 +template <class T, class Method, class Params>
   1.662 +class UnboundMethod {
   1.663 + public:
   1.664 +  UnboundMethod(Method m, Params p) : m_(m), p_(p) {}
   1.665 +  void Run(T* obj) const {
   1.666 +    DispatchToMethod(obj, m_, p_);
   1.667 +  }
   1.668 + private:
   1.669 +  Method m_;
   1.670 +  Params p_;
   1.671 +};
   1.672 +
   1.673 +#endif  // BASE_TASK_H_

mercurial