1 // Copyright (c) 2011 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/base_api.h" 10 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/tracked.h" 13 #include "base/tuple.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 20 class BASE_API 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 29 class BASE_API 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. 83 template<class T> 84 class 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( 153 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 154 badscopedrunnablemethodparams); 155 } 156 157 virtual void Run() { 158 if (obj_) 159 DispatchToMethod(obj_.get(), meth_, params_); 160 } 161 162 virtual void Cancel() { 163 obj_.reset(); 164 } 165 166 private: 167 base::WeakPtr<T> obj_; 168 Method meth_; 169 Params params_; 170 171 DISALLOW_COPY_AND_ASSIGN(RunnableMethod); 172 }; 173 174 private: 175 base::WeakPtrFactory<T> weak_factory_; 176 }; 177 178 // General task implementations ------------------------------------------------ 179 180 // Task to delete an object 181 template<class T> 182 class DeleteTask : public CancelableTask { 183 public: 184 explicit DeleteTask(const T* obj) : obj_(obj) { 185 } 186 virtual void Run() { 187 delete obj_; 188 } 189 virtual void Cancel() { 190 obj_ = NULL; 191 } 192 193 private: 194 const T* obj_; 195 }; 196 197 // Task to Release() an object 198 template<class T> 199 class ReleaseTask : public CancelableTask { 200 public: 201 explicit ReleaseTask(const T* obj) : obj_(obj) { 202 } 203 virtual void Run() { 204 if (obj_) 205 obj_->Release(); 206 } 207 virtual void Cancel() { 208 obj_ = NULL; 209 } 210 211 private: 212 const T* obj_; 213 }; 214 215 // RunnableMethodTraits -------------------------------------------------------- 216 // 217 // This traits-class is used by RunnableMethod to manage the lifetime of the 218 // callee object. By default, it is assumed that the callee supports AddRef 219 // and Release methods. A particular class can specialize this template to 220 // define other lifetime management. For example, if the callee is known to 221 // live longer than the RunnableMethod object, then a RunnableMethodTraits 222 // struct could be defined with empty RetainCallee and ReleaseCallee methods. 223 // 224 // The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way 225 // for declaring a RunnableMethodTraits that disables refcounting. 226 227 template <class T> 228 struct RunnableMethodTraits { 229 RunnableMethodTraits() { 230 #ifndef NDEBUG 231 origin_thread_id_ = base::PlatformThread::CurrentId(); 232 #endif 233 } 234 235 ~RunnableMethodTraits() { 236 #ifndef NDEBUG 237 // If destroyed on a separate thread, then we had better have been using 238 // thread-safe reference counting! 239 if (origin_thread_id_ != base::PlatformThread::CurrentId()) 240 DCHECK(T::ImplementsThreadSafeReferenceCounting()); 241 #endif 242 } 243 244 void RetainCallee(T* obj) { 245 #ifndef NDEBUG 246 // Catch NewRunnableMethod being called in an object's constructor. This 247 // isn't safe since the method can be invoked before the constructor 248 // completes, causing the object to be deleted. 249 obj->AddRef(); 250 obj->Release(); 251 #endif 252 obj->AddRef(); 253 } 254 255 void ReleaseCallee(T* obj) { 256 obj->Release(); 257 } 258 259 private: 260 #ifndef NDEBUG 261 base::PlatformThreadId origin_thread_id_; 262 #endif 263 }; 264 265 // Convenience macro for declaring a RunnableMethodTraits that disables 266 // refcounting of a class. This is useful if you know that the callee 267 // will outlive the RunnableMethod object and thus do not need the ref counts. 268 // 269 // The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the 270 // global namespace scope. Example: 271 // 272 // namespace foo { 273 // class Bar { 274 // ... 275 // }; 276 // } // namespace foo 277 // 278 // DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar); 279 // 280 // This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the 281 // class. 282 #define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \ 283 template <> \ 284 struct RunnableMethodTraits<TypeName> { \ 285 void RetainCallee(TypeName* manager) {} \ 286 void ReleaseCallee(TypeName* manager) {} \ 287 } 288 289 // RunnableMethod and RunnableFunction ----------------------------------------- 290 // 291 // Runnable methods are a type of task that call a function on an object when 292 // they are run. We implement both an object and a set of NewRunnableMethod and 293 // NewRunnableFunction functions for convenience. These functions are 294 // overloaded and will infer the template types, simplifying calling code. 295 // 296 // The template definitions all use the following names: 297 // T - the class type of the object you're supplying 298 // this is not needed for the Static version of the call 299 // Method/Function - the signature of a pointer to the method or function you 300 // want to call 301 // Param - the parameter(s) to the method, possibly packed as a Tuple 302 // A - the first parameter (if any) to the method 303 // B - the second parameter (if any) to the method 304 // 305 // Put these all together and you get an object that can call a method whose 306 // signature is: 307 // R T::MyFunction([A[, B]]) 308 // 309 // Usage: 310 // PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]]) 311 // PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]]) 312 313 // RunnableMethod and NewRunnableMethod implementation ------------------------- 314 315 template <class T, class Method, class Params> 316 class RunnableMethod : public CancelableTask { 317 public: 318 RunnableMethod(T* obj, Method meth, const Params& params) 319 : obj_(obj), meth_(meth), params_(params) { 320 traits_.RetainCallee(obj_); 321 COMPILE_ASSERT( 322 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 323 badrunnablemethodparams); 324 } 325 326 ~RunnableMethod() { 327 ReleaseCallee(); 328 } 329 330 virtual void Run() { 331 if (obj_) 332 DispatchToMethod(obj_, meth_, params_); 333 } 334 335 virtual void Cancel() { 336 ReleaseCallee(); 337 } 338 339 private: 340 void ReleaseCallee() { 341 T* obj = obj_; 342 obj_ = NULL; 343 if (obj) 344 traits_.ReleaseCallee(obj); 345 } 346 347 T* obj_; 348 Method meth_; 349 Params params_; 350 RunnableMethodTraits<T> traits_; 351 }; 352 353 template <class T, class Method> 354 inline CancelableTask* NewRunnableMethod(T* object, Method method) { 355 return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); 356 } 357 358 template <class T, class Method, class A> 359 inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) { 360 return new RunnableMethod<T, Method, Tuple1<A> >(object, 361 method, 362 MakeTuple(a)); 363 } 364 365 template <class T, class Method, class A, class B> 366 inline CancelableTask* NewRunnableMethod(T* object, Method method, 367 const A& a, const B& b) { 368 return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, 369 MakeTuple(a, b)); 370 } 371 372 template <class T, class Method, class A, class B, class C> 373 inline CancelableTask* NewRunnableMethod(T* object, Method method, 374 const A& a, const B& b, const C& c) { 375 return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method, 376 MakeTuple(a, b, c)); 377 } 378 379 template <class T, class Method, class A, class B, class C, class D> 380 inline CancelableTask* NewRunnableMethod(T* object, Method method, 381 const A& a, const B& b, 382 const C& c, const D& d) { 383 return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method, 384 MakeTuple(a, b, 385 c, d)); 386 } 387 388 template <class T, class Method, class A, class B, class C, class D, class E> 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 return new RunnableMethod<T, 393 Method, 394 Tuple5<A, B, C, D, E> >(object, 395 method, 396 MakeTuple(a, b, c, d, e)); 397 } 398 399 template <class T, class Method, class A, class B, class C, class D, class E, 400 class F> 401 inline CancelableTask* NewRunnableMethod(T* object, Method method, 402 const A& a, const B& b, 403 const C& c, const D& d, const E& e, 404 const F& f) { 405 return new RunnableMethod<T, 406 Method, 407 Tuple6<A, B, C, D, E, F> >(object, 408 method, 409 MakeTuple(a, b, c, d, e, 410 f)); 411 } 412 413 template <class T, class Method, class A, class B, class C, class D, class E, 414 class F, class G> 415 inline CancelableTask* NewRunnableMethod(T* object, Method method, 416 const A& a, const B& b, 417 const C& c, const D& d, const E& e, 418 const F& f, const G& g) { 419 return new RunnableMethod<T, 420 Method, 421 Tuple7<A, B, C, D, E, F, G> >(object, 422 method, 423 MakeTuple(a, b, c, d, 424 e, f, g)); 425 } 426 427 template <class T, class Method, class A, class B, class C, class D, class E, 428 class F, class G, class H> 429 inline CancelableTask* NewRunnableMethod(T* object, Method method, 430 const A& a, const B& b, 431 const C& c, const D& d, const E& e, 432 const F& f, const G& g, const H& h) { 433 return new RunnableMethod<T, 434 Method, 435 Tuple8<A, B, C, D, E, F, G, H> >(object, 436 method, 437 MakeTuple(a, b, c, 438 d, e, f, 439 g, h)); 440 } 441 442 // RunnableFunction and NewRunnableFunction implementation --------------------- 443 444 template <class Function, class Params> 445 class RunnableFunction : public CancelableTask { 446 public: 447 RunnableFunction(Function function, const Params& params) 448 : function_(function), params_(params) { 449 COMPILE_ASSERT( 450 (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), 451 badrunnablefunctionparams); 452 } 453 454 ~RunnableFunction() { 455 } 456 457 virtual void Run() { 458 if (function_) 459 DispatchToFunction(function_, params_); 460 } 461 462 virtual void Cancel() { 463 } 464 465 private: 466 Function function_; 467 Params params_; 468 }; 469 470 template <class Function> 471 inline CancelableTask* NewRunnableFunction(Function function) { 472 return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); 473 } 474 475 template <class Function, class A> 476 inline CancelableTask* NewRunnableFunction(Function function, const A& a) { 477 return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); 478 } 479 480 template <class Function, class A, class B> 481 inline CancelableTask* NewRunnableFunction(Function function, 482 const A& a, const B& b) { 483 return new RunnableFunction<Function, Tuple2<A, B> >(function, 484 MakeTuple(a, b)); 485 } 486 487 template <class Function, class A, class B, class C> 488 inline CancelableTask* NewRunnableFunction(Function function, 489 const A& a, const B& b, 490 const C& c) { 491 return new RunnableFunction<Function, Tuple3<A, B, C> >(function, 492 MakeTuple(a, b, c)); 493 } 494 495 template <class Function, class A, class B, class C, class D> 496 inline CancelableTask* NewRunnableFunction(Function function, 497 const A& a, const B& b, 498 const C& c, const D& d) { 499 return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function, 500 MakeTuple(a, b, 501 c, d)); 502 } 503 504 template <class Function, class A, class B, class C, class D, class E> 505 inline CancelableTask* NewRunnableFunction(Function function, 506 const A& a, const B& b, 507 const C& c, const D& d, 508 const E& e) { 509 return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function, 510 MakeTuple(a, b, 511 c, d, 512 e)); 513 } 514 515 template <class Function, class A, class B, class C, class D, class E, 516 class F> 517 inline CancelableTask* NewRunnableFunction(Function function, 518 const A& a, const B& b, 519 const C& c, const D& d, 520 const E& e, const F& f) { 521 return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function, 522 MakeTuple(a, b, c, d, e, f)); 523 } 524 525 template <class Function, class A, class B, class C, class D, class E, 526 class F, class G> 527 inline CancelableTask* NewRunnableFunction(Function function, 528 const A& a, const B& b, 529 const C& c, const D& d, 530 const E& e, const F& f, 531 const G& g) { 532 return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function, 533 MakeTuple(a, b, c, d, e, f, g)); 534 } 535 536 template <class Function, class A, class B, class C, class D, class E, 537 class F, class G, class H> 538 inline CancelableTask* NewRunnableFunction(Function function, 539 const A& a, const B& b, 540 const C& c, const D& d, 541 const E& e, const F& f, 542 const G& g, const H& h) { 543 return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >( 544 function, MakeTuple(a, b, c, d, e, f, g, h)); 545 } 546 547 #endif // BASE_TASK_H_ 548