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.

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

mercurial