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