task.h revision 3f50c38dc070f4bb515c1b64450dae14f316474e
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#pragma once 8 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 CancelableTask(); 31 virtual ~CancelableTask(); 32 33 // Not all tasks support cancellation. 34 virtual void Cancel() = 0; 35}; 36 37// Scoped Factories ------------------------------------------------------------ 38// 39// These scoped factory objects can be used by non-refcounted objects to safely 40// place tasks in a message loop. Each factory guarantees that the tasks it 41// produces will not run after the factory is destroyed. Commonly, factories 42// are declared as class members, so the class' tasks will automatically cancel 43// when the class instance is destroyed. 44// 45// Exampe Usage: 46// 47// class MyClass { 48// private: 49// // This factory will be used to schedule invocations of SomeMethod. 50// ScopedRunnableMethodFactory<MyClass> some_method_factory_; 51// 52// public: 53// // It is safe to suppress warning 4355 here. 54// MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { } 55// 56// void SomeMethod() { 57// // If this function might be called directly, you might want to revoke 58// // any outstanding runnable methods scheduled to call it. If it's not 59// // referenced other than by the factory, this is unnecessary. 60// some_method_factory_.RevokeAll(); 61// ... 62// } 63// 64// void ScheduleSomeMethod() { 65// // If you'd like to only only have one pending task at a time, test for 66// // |empty| before manufacturing another task. 67// if (!some_method_factory_.empty()) 68// return; 69// 70// // The factories are not thread safe, so always invoke on 71// // |MessageLoop::current()|. 72// MessageLoop::current()->PostDelayedTask( 73// FROM_HERE, 74// some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod), 75// kSomeMethodDelayMS); 76// } 77// }; 78 79// A ScopedRunnableMethodFactory creates runnable methods for a specified 80// object. This is particularly useful for generating callbacks for 81// non-reference counted objects when the factory is a member of the object. 82template<class T> 83class ScopedRunnableMethodFactory { 84 public: 85 explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) { 86 } 87 88 template <class Method> 89 inline CancelableTask* NewRunnableMethod(Method method) { 90 return new RunnableMethod<Method, Tuple0>( 91 weak_factory_.GetWeakPtr(), method, MakeTuple()); 92 } 93 94 template <class Method, class A> 95 inline CancelableTask* NewRunnableMethod(Method method, const A& a) { 96 return new RunnableMethod<Method, Tuple1<A> >( 97 weak_factory_.GetWeakPtr(), method, MakeTuple(a)); 98 } 99 100 template <class Method, class A, class B> 101 inline CancelableTask* NewRunnableMethod(Method method, const A& a, 102 const B& b) { 103 return new RunnableMethod<Method, Tuple2<A, B> >( 104 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b)); 105 } 106 107 template <class Method, class A, class B, class C> 108 inline CancelableTask* NewRunnableMethod(Method method, 109 const A& a, 110 const B& b, 111 const C& c) { 112 return new RunnableMethod<Method, Tuple3<A, B, C> >( 113 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c)); 114 } 115 116 template <class Method, class A, class B, class C, class D> 117 inline CancelableTask* NewRunnableMethod(Method method, 118 const A& a, 119 const B& b, 120 const C& c, 121 const D& d) { 122 return new RunnableMethod<Method, Tuple4<A, B, C, D> >( 123 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d)); 124 } 125 126 template <class Method, class A, class B, class C, class D, class E> 127 inline CancelableTask* NewRunnableMethod(Method method, 128 const A& a, 129 const B& b, 130 const C& c, 131 const D& d, 132 const E& e) { 133 return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >( 134 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e)); 135 } 136 137 void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } 138 139 bool empty() const { return !weak_factory_.HasWeakPtrs(); } 140 141 protected: 142 template <class Method, class Params> 143 class RunnableMethod : public CancelableTask { 144 public: 145 RunnableMethod(const base::WeakPtr<T>& obj, 146 Method meth, 147 const Params& params) 148 : obj_(obj), 149 meth_(meth), 150 params_(params) { 151 COMPILE_ASSERT( 152 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 153 badscopedrunnablemethodparams); 154 } 155 156 virtual void Run() { 157 if (obj_) 158 DispatchToMethod(obj_.get(), meth_, params_); 159 } 160 161 virtual void Cancel() { 162 obj_.reset(); 163 } 164 165 private: 166 base::WeakPtr<T> obj_; 167 Method meth_; 168 Params params_; 169 170 DISALLOW_COPY_AND_ASSIGN(RunnableMethod); 171 }; 172 173 private: 174 base::WeakPtrFactory<T> weak_factory_; 175}; 176 177// General task implementations ------------------------------------------------ 178 179// Task to delete an object 180template<class T> 181class DeleteTask : public CancelableTask { 182 public: 183 explicit DeleteTask(const T* obj) : obj_(obj) { 184 } 185 virtual void Run() { 186 delete obj_; 187 } 188 virtual void Cancel() { 189 obj_ = NULL; 190 } 191 192 private: 193 const T* obj_; 194}; 195 196// Task to Release() an object 197template<class T> 198class ReleaseTask : public CancelableTask { 199 public: 200 explicit ReleaseTask(const T* obj) : obj_(obj) { 201 } 202 virtual void Run() { 203 if (obj_) 204 obj_->Release(); 205 } 206 virtual void Cancel() { 207 obj_ = NULL; 208 } 209 210 private: 211 const T* obj_; 212}; 213 214// RunnableMethodTraits -------------------------------------------------------- 215// 216// This traits-class is used by RunnableMethod to manage the lifetime of the 217// callee object. By default, it is assumed that the callee supports AddRef 218// and Release methods. A particular class can specialize this template to 219// define other lifetime management. For example, if the callee is known to 220// live longer than the RunnableMethod object, then a RunnableMethodTraits 221// struct could be defined with empty RetainCallee and ReleaseCallee methods. 222// 223// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way 224// for declaring a RunnableMethodTraits that disables refcounting. 225 226template <class T> 227struct RunnableMethodTraits { 228 RunnableMethodTraits() { 229#ifndef NDEBUG 230 origin_thread_id_ = base::PlatformThread::CurrentId(); 231#endif 232 } 233 234 ~RunnableMethodTraits() { 235#ifndef NDEBUG 236 // If destroyed on a separate thread, then we had better have been using 237 // thread-safe reference counting! 238 if (origin_thread_id_ != base::PlatformThread::CurrentId()) 239 DCHECK(T::ImplementsThreadSafeReferenceCounting()); 240#endif 241 } 242 243 void RetainCallee(T* obj) { 244#ifndef NDEBUG 245 // Catch NewRunnableMethod being called in an object's constructor. This 246 // isn't safe since the method can be invoked before the constructor 247 // completes, causing the object to be deleted. 248 obj->AddRef(); 249 obj->Release(); 250#endif 251 obj->AddRef(); 252 } 253 254 void ReleaseCallee(T* obj) { 255 obj->Release(); 256 } 257 258 private: 259#ifndef NDEBUG 260 base::PlatformThreadId origin_thread_id_; 261#endif 262}; 263 264// Convenience macro for declaring a RunnableMethodTraits that disables 265// refcounting of a class. This is useful if you know that the callee 266// will outlive the RunnableMethod object and thus do not need the ref counts. 267// 268// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the 269// global namespace scope. Example: 270// 271// namespace foo { 272// class Bar { 273// ... 274// }; 275// } // namespace foo 276// 277// DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar); 278// 279// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the 280// class. 281#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \ 282 template <> \ 283 struct RunnableMethodTraits<TypeName> { \ 284 void RetainCallee(TypeName* manager) {} \ 285 void ReleaseCallee(TypeName* manager) {} \ 286 } 287 288// RunnableMethod and RunnableFunction ----------------------------------------- 289// 290// Runnable methods are a type of task that call a function on an object when 291// they are run. We implement both an object and a set of NewRunnableMethod and 292// NewRunnableFunction functions for convenience. These functions are 293// overloaded and will infer the template types, simplifying calling code. 294// 295// The template definitions all use the following names: 296// T - the class type of the object you're supplying 297// this is not needed for the Static version of the call 298// Method/Function - the signature of a pointer to the method or function you 299// want to call 300// Param - the parameter(s) to the method, possibly packed as a Tuple 301// A - the first parameter (if any) to the method 302// B - the second parameter (if any) to the method 303// 304// Put these all together and you get an object that can call a method whose 305// signature is: 306// R T::MyFunction([A[, B]]) 307// 308// Usage: 309// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]]) 310// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]]) 311 312// RunnableMethod and NewRunnableMethod implementation ------------------------- 313 314template <class T, class Method, class Params> 315class RunnableMethod : public CancelableTask { 316 public: 317 RunnableMethod(T* obj, Method meth, const Params& params) 318 : obj_(obj), meth_(meth), params_(params) { 319 traits_.RetainCallee(obj_); 320 COMPILE_ASSERT( 321 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 322 badrunnablemethodparams); 323 } 324 325 ~RunnableMethod() { 326 ReleaseCallee(); 327 } 328 329 virtual void Run() { 330 if (obj_) 331 DispatchToMethod(obj_, meth_, params_); 332 } 333 334 virtual void Cancel() { 335 ReleaseCallee(); 336 } 337 338 private: 339 void ReleaseCallee() { 340 T* obj = obj_; 341 obj_ = NULL; 342 if (obj) 343 traits_.ReleaseCallee(obj); 344 } 345 346 T* obj_; 347 Method meth_; 348 Params params_; 349 RunnableMethodTraits<T> traits_; 350}; 351 352template <class T, class Method> 353inline CancelableTask* NewRunnableMethod(T* object, Method method) { 354 return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); 355} 356 357template <class T, class Method, class A> 358inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) { 359 return new RunnableMethod<T, Method, Tuple1<A> >(object, 360 method, 361 MakeTuple(a)); 362} 363 364template <class T, class Method, class A, class B> 365inline CancelableTask* NewRunnableMethod(T* object, Method method, 366const A& a, const B& b) { 367 return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, 368 MakeTuple(a, b)); 369} 370 371template <class T, class Method, class A, class B, class C> 372inline CancelableTask* NewRunnableMethod(T* object, Method method, 373 const A& a, const B& b, const C& c) { 374 return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method, 375 MakeTuple(a, b, c)); 376} 377 378template <class T, class Method, class A, class B, class C, class D> 379inline CancelableTask* NewRunnableMethod(T* object, Method method, 380 const A& a, const B& b, 381 const C& c, const D& d) { 382 return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method, 383 MakeTuple(a, b, 384 c, d)); 385} 386 387template <class T, class Method, class A, class B, class C, class D, class E> 388inline CancelableTask* NewRunnableMethod(T* object, Method method, 389 const A& a, const B& b, 390 const C& c, const D& d, const E& e) { 391 return new RunnableMethod<T, 392 Method, 393 Tuple5<A, B, C, D, E> >(object, 394 method, 395 MakeTuple(a, b, c, d, e)); 396} 397 398template <class T, class Method, class A, class B, class C, class D, class E, 399 class F> 400inline CancelableTask* NewRunnableMethod(T* object, Method method, 401 const A& a, const B& b, 402 const C& c, const D& d, const E& e, 403 const F& f) { 404 return new RunnableMethod<T, 405 Method, 406 Tuple6<A, B, C, D, E, F> >(object, 407 method, 408 MakeTuple(a, b, c, d, e, 409 f)); 410} 411 412template <class T, class Method, class A, class B, class C, class D, class E, 413 class F, class G> 414inline CancelableTask* NewRunnableMethod(T* object, Method method, 415 const A& a, const B& b, 416 const C& c, const D& d, const E& e, 417 const F& f, const G& g) { 418 return new RunnableMethod<T, 419 Method, 420 Tuple7<A, B, C, D, E, F, G> >(object, 421 method, 422 MakeTuple(a, b, c, d, 423 e, f, g)); 424} 425 426// RunnableFunction and NewRunnableFunction implementation --------------------- 427 428template <class Function, class Params> 429class RunnableFunction : public CancelableTask { 430 public: 431 RunnableFunction(Function function, const Params& params) 432 : function_(function), params_(params) { 433 COMPILE_ASSERT( 434 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 435 badrunnablefunctionparams); 436 } 437 438 ~RunnableFunction() { 439 } 440 441 virtual void Run() { 442 if (function_) 443 DispatchToFunction(function_, params_); 444 } 445 446 virtual void Cancel() { 447 } 448 449 private: 450 Function function_; 451 Params params_; 452}; 453 454template <class Function> 455inline CancelableTask* NewRunnableFunction(Function function) { 456 return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); 457} 458 459template <class Function, class A> 460inline CancelableTask* NewRunnableFunction(Function function, const A& a) { 461 return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); 462} 463 464template <class Function, class A, class B> 465inline CancelableTask* NewRunnableFunction(Function function, 466 const A& a, const B& b) { 467 return new RunnableFunction<Function, Tuple2<A, B> >(function, 468 MakeTuple(a, b)); 469} 470 471template <class Function, class A, class B, class C> 472inline CancelableTask* NewRunnableFunction(Function function, 473 const A& a, const B& b, 474 const C& c) { 475 return new RunnableFunction<Function, Tuple3<A, B, C> >(function, 476 MakeTuple(a, b, c)); 477} 478 479template <class Function, class A, class B, class C, class D> 480inline CancelableTask* NewRunnableFunction(Function function, 481 const A& a, const B& b, 482 const C& c, const D& d) { 483 return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function, 484 MakeTuple(a, b, 485 c, d)); 486} 487 488template <class Function, class A, class B, class C, class D, class E> 489inline CancelableTask* NewRunnableFunction(Function function, 490 const A& a, const B& b, 491 const C& c, const D& d, 492 const E& e) { 493 return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function, 494 MakeTuple(a, b, 495 c, d, 496 e)); 497} 498 499template <class Function, class A, class B, class C, class D, class E, 500 class F> 501inline CancelableTask* NewRunnableFunction(Function function, 502 const A& a, const B& b, 503 const C& c, const D& d, 504 const E& e, const F& f) { 505 return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function, 506 MakeTuple(a, b, c, d, e, f)); 507} 508 509template <class Function, class A, class B, class C, class D, class E, 510 class F, class G> 511inline CancelableTask* NewRunnableFunction(Function function, 512 const A& a, const B& b, 513 const C& c, const D& d, 514 const E& e, const F& f, 515 const G& g) { 516 return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function, 517 MakeTuple(a, b, c, d, e, f, g)); 518} 519 520template <class Function, class A, class B, class C, class D, class E, 521 class F, class G, class H> 522inline CancelableTask* NewRunnableFunction(Function function, 523 const A& a, const B& b, 524 const C& c, const D& d, 525 const E& e, const F& f, 526 const G& g, const H& h) { 527 return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >( 528 function, MakeTuple(a, b, c, d, e, f, g, h)); 529} 530 531#endif // BASE_TASK_H_ 532