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_
|