task.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
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/non_thread_safe.h" 10#include "base/raw_scoped_refptr_mismatch_checker.h" 11#include "base/tracked.h" 12#include "base/tuple.h" 13#include "base/weak_ptr.h" 14 15// Task ------------------------------------------------------------------------ 16// 17// A task is a generic runnable thingy, usually used for running code on a 18// different thread or for scheduling future tasks off of the message loop. 19 20class Task : public tracked_objects::Tracked { 21 public: 22 Task(); 23 virtual ~Task(); 24 25 // Tasks are automatically deleted after Run is called. 26 virtual void Run() = 0; 27}; 28 29class CancelableTask : public Task { 30 public: 31 CancelableTask(); 32 virtual ~CancelableTask(); 33 34 // Not all tasks support cancellation. 35 virtual void Cancel() = 0; 36}; 37 38// Scoped Factories ------------------------------------------------------------ 39// 40// These scoped factory objects can be used by non-refcounted objects to safely 41// place tasks in a message loop. Each factory guarantees that the tasks it 42// produces will not run after the factory is destroyed. Commonly, factories 43// are declared as class members, so the class' tasks will automatically cancel 44// when the class instance is destroyed. 45// 46// Exampe Usage: 47// 48// class MyClass { 49// private: 50// // This factory will be used to schedule invocations of SomeMethod. 51// ScopedRunnableMethodFactory<MyClass> some_method_factory_; 52// 53// public: 54// // It is safe to suppress warning 4355 here. 55// MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { } 56// 57// void SomeMethod() { 58// // If this function might be called directly, you might want to revoke 59// // any outstanding runnable methods scheduled to call it. If it's not 60// // referenced other than by the factory, this is unnecessary. 61// some_method_factory_.RevokeAll(); 62// ... 63// } 64// 65// void ScheduleSomeMethod() { 66// // If you'd like to only only have one pending task at a time, test for 67// // |empty| before manufacturing another task. 68// if (!some_method_factory_.empty()) 69// return; 70// 71// // The factories are not thread safe, so always invoke on 72// // |MessageLoop::current()|. 73// MessageLoop::current()->PostDelayedTask( 74// FROM_HERE, 75// some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod), 76// kSomeMethodDelayMS); 77// } 78// }; 79 80// A ScopedRunnableMethodFactory creates runnable methods for a specified 81// object. This is particularly useful for generating callbacks for 82// non-reference counted objects when the factory is a member of the object. 83template<class T> 84class ScopedRunnableMethodFactory { 85 public: 86 explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) { 87 } 88 89 template <class Method> 90 inline CancelableTask* NewRunnableMethod(Method method) { 91 return new RunnableMethod<Method, Tuple0>( 92 weak_factory_.GetWeakPtr(), method, MakeTuple()); 93 } 94 95 template <class Method, class A> 96 inline CancelableTask* NewRunnableMethod(Method method, const A& a) { 97 return new RunnableMethod<Method, Tuple1<A> >( 98 weak_factory_.GetWeakPtr(), method, MakeTuple(a)); 99 } 100 101 template <class Method, class A, class B> 102 inline CancelableTask* NewRunnableMethod(Method method, const A& a, 103 const B& b) { 104 return new RunnableMethod<Method, Tuple2<A, B> >( 105 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b)); 106 } 107 108 template <class Method, class A, class B, class C> 109 inline CancelableTask* NewRunnableMethod(Method method, 110 const A& a, 111 const B& b, 112 const C& c) { 113 return new RunnableMethod<Method, Tuple3<A, B, C> >( 114 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c)); 115 } 116 117 template <class Method, class A, class B, class C, class D> 118 inline CancelableTask* NewRunnableMethod(Method method, 119 const A& a, 120 const B& b, 121 const C& c, 122 const D& d) { 123 return new RunnableMethod<Method, Tuple4<A, B, C, D> >( 124 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d)); 125 } 126 127 template <class Method, class A, class B, class C, class D, class E> 128 inline CancelableTask* NewRunnableMethod(Method method, 129 const A& a, 130 const B& b, 131 const C& c, 132 const D& d, 133 const E& e) { 134 return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >( 135 weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e)); 136 } 137 138 void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } 139 140 bool empty() const { return !weak_factory_.HasWeakPtrs(); } 141 142 protected: 143 template <class Method, class Params> 144 class RunnableMethod : public CancelableTask { 145 public: 146 RunnableMethod(const base::WeakPtr<T>& obj, 147 Method meth, 148 const Params& params) 149 : obj_(obj), 150 meth_(meth), 151 params_(params) { 152 COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, 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(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 T* obj_; 194}; 195 196// Task to Release() an object 197template<class T> 198class ReleaseTask : public CancelableTask { 199 public: 200 explicit ReleaseTask(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 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_ = 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_ != 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 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((MethodUsesScopedRefptrCorrectly<Method, Params>::value), 321 badrunnablemethodparams); 322 } 323 324 ~RunnableMethod() { 325 ReleaseCallee(); 326 } 327 328 virtual void Run() { 329 if (obj_) 330 DispatchToMethod(obj_, meth_, params_); 331 } 332 333 virtual void Cancel() { 334 ReleaseCallee(); 335 } 336 337 private: 338 void ReleaseCallee() { 339 if (obj_) { 340 traits_.ReleaseCallee(obj_); 341 obj_ = NULL; 342 } 343 } 344 345 T* obj_; 346 Method meth_; 347 Params params_; 348 RunnableMethodTraits<T> traits_; 349}; 350 351template <class T, class Method> 352inline CancelableTask* NewRunnableMethod(T* object, Method method) { 353 return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); 354} 355 356template <class T, class Method, class A> 357inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) { 358 return new RunnableMethod<T, Method, Tuple1<A> >(object, 359 method, 360 MakeTuple(a)); 361} 362 363template <class T, class Method, class A, class B> 364inline CancelableTask* NewRunnableMethod(T* object, Method method, 365const A& a, const B& b) { 366 return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, 367 MakeTuple(a, b)); 368} 369 370template <class T, class Method, class A, class B, class C> 371inline CancelableTask* NewRunnableMethod(T* object, Method method, 372 const A& a, const B& b, const C& c) { 373 return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method, 374 MakeTuple(a, b, c)); 375} 376 377template <class T, class Method, class A, class B, class C, class D> 378inline CancelableTask* NewRunnableMethod(T* object, Method method, 379 const A& a, const B& b, 380 const C& c, const D& d) { 381 return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method, 382 MakeTuple(a, b, 383 c, d)); 384} 385 386template <class T, class Method, class A, class B, class C, class D, class E> 387inline CancelableTask* NewRunnableMethod(T* object, Method method, 388 const A& a, const B& b, 389 const C& c, const D& d, const E& e) { 390 return new RunnableMethod<T, 391 Method, 392 Tuple5<A, B, C, D, E> >(object, 393 method, 394 MakeTuple(a, b, c, d, e)); 395} 396 397template <class T, class Method, class A, class B, class C, class D, class E, 398 class F> 399inline CancelableTask* NewRunnableMethod(T* object, Method method, 400 const A& a, const B& b, 401 const C& c, const D& d, const E& e, 402 const F& f) { 403 return new RunnableMethod<T, 404 Method, 405 Tuple6<A, B, C, D, E, F> >(object, 406 method, 407 MakeTuple(a, b, c, d, e, 408 f)); 409} 410 411template <class T, class Method, class A, class B, class C, class D, class E, 412 class F, class G> 413inline CancelableTask* NewRunnableMethod(T* object, Method method, 414 const A& a, const B& b, 415 const C& c, const D& d, const E& e, 416 const F& f, const G& g) { 417 return new RunnableMethod<T, 418 Method, 419 Tuple7<A, B, C, D, E, F, G> >(object, 420 method, 421 MakeTuple(a, b, c, d, 422 e, f, g)); 423} 424 425// RunnableFunction and NewRunnableFunction implementation --------------------- 426 427template <class Function, class Params> 428class RunnableFunction : public CancelableTask { 429 public: 430 RunnableFunction(Function function, const Params& params) 431 : function_(function), params_(params) { 432 COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value), 433 badrunnablefunctionparams); 434 } 435 436 ~RunnableFunction() { 437 } 438 439 virtual void Run() { 440 if (function_) 441 DispatchToFunction(function_, params_); 442 } 443 444 virtual void Cancel() { 445 } 446 447 private: 448 Function function_; 449 Params params_; 450}; 451 452template <class Function> 453inline CancelableTask* NewRunnableFunction(Function function) { 454 return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); 455} 456 457template <class Function, class A> 458inline CancelableTask* NewRunnableFunction(Function function, const A& a) { 459 return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); 460} 461 462template <class Function, class A, class B> 463inline CancelableTask* NewRunnableFunction(Function function, 464 const A& a, const B& b) { 465 return new RunnableFunction<Function, Tuple2<A, B> >(function, 466 MakeTuple(a, b)); 467} 468 469template <class Function, class A, class B, class C> 470inline CancelableTask* NewRunnableFunction(Function function, 471 const A& a, const B& b, 472 const C& c) { 473 return new RunnableFunction<Function, Tuple3<A, B, C> >(function, 474 MakeTuple(a, b, c)); 475} 476 477template <class Function, class A, class B, class C, class D> 478inline CancelableTask* NewRunnableFunction(Function function, 479 const A& a, const B& b, 480 const C& c, const D& d) { 481 return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function, 482 MakeTuple(a, b, 483 c, d)); 484} 485 486template <class Function, class A, class B, class C, class D, class E> 487inline CancelableTask* NewRunnableFunction(Function function, 488 const A& a, const B& b, 489 const C& c, const D& d, 490 const E& e) { 491 return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function, 492 MakeTuple(a, b, 493 c, d, 494 e)); 495} 496 497template <class Function, class A, class B, class C, class D, class E, 498 class F> 499inline CancelableTask* NewRunnableFunction(Function function, 500 const A& a, const B& b, 501 const C& c, const D& d, 502 const E& e, const F& f) { 503 return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function, 504 MakeTuple(a, b, c, d, e, f)); 505} 506 507template <class Function, class A, class B, class C, class D, class E, 508 class F, class G> 509inline CancelableTask* NewRunnableFunction(Function function, 510 const A& a, const B& b, 511 const C& c, const D& d, 512 const E& e, const F& f, 513 const G& g) { 514 return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function, 515 MakeTuple(a, b, c, d, e, f, g)); 516} 517 518template <class Function, class A, class B, class C, class D, class E, 519 class F, class G, class H> 520inline CancelableTask* NewRunnableFunction(Function function, 521 const A& a, const B& b, 522 const C& c, const D& d, 523 const E& e, const F& f, 524 const G& g, const H& h) { 525 return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >( 526 function, MakeTuple(a, b, c, d, e, f, g, h)); 527} 528 529#endif // BASE_TASK_H_ 530