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 20class 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 29class 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. 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( 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 181template<class T> 182class 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 198template<class T> 199class 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 227template <class T> 228struct 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 315template <class T, class Method, class Params> 316class 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 353template <class T, class Method> 354inline CancelableTask* NewRunnableMethod(T* object, Method method) { 355 return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); 356} 357 358template <class T, class Method, class A> 359inline 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 365template <class T, class Method, class A, class B> 366inline CancelableTask* NewRunnableMethod(T* object, Method method, 367const A& a, const B& b) { 368 return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, 369 MakeTuple(a, b)); 370} 371 372template <class T, class Method, class A, class B, class C> 373inline 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 379template <class T, class Method, class A, class B, class C, class D> 380inline 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 388template <class T, class Method, class A, class B, class C, class D, class E> 389inline 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 399template <class T, class Method, class A, class B, class C, class D, class E, 400 class F> 401inline 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 413template <class T, class Method, class A, class B, class C, class D, class E, 414 class F, class G> 415inline 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 427template <class T, class Method, class A, class B, class C, class D, class E, 428 class F, class G, class H> 429inline 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 444template <class Function, class Params> 445class 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 470template <class Function> 471inline CancelableTask* NewRunnableFunction(Function function) { 472 return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); 473} 474 475template <class Function, class A> 476inline CancelableTask* NewRunnableFunction(Function function, const A& a) { 477 return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); 478} 479 480template <class Function, class A, class B> 481inline 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 487template <class Function, class A, class B, class C> 488inline 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 495template <class Function, class A, class B, class C, class D> 496inline 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 504template <class Function, class A, class B, class C, class D, class E> 505inline 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 515template <class Function, class A, class B, class C, class D, class E, 516 class F> 517inline 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 525template <class Function, class A, class B, class C, class D, class E, 526 class F, class G> 527inline 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 536template <class Function, class A, class B, class C, class D, class E, 537 class F, class G, class H> 538inline 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