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:
ScopedRunnableMethodFactory(T * object)86 explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) {
87 }
88
89 template <class Method>
NewRunnableMethod(Method 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>
NewRunnableMethod(Method method,const A & 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>
NewRunnableMethod(Method method,const A & a,const B & 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>
NewRunnableMethod(Method method,const A & a,const B & b,const C & 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>
NewRunnableMethod(Method method,const A & a,const B & b,const C & c,const D & 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>
NewRunnableMethod(Method method,const A & a,const B & b,const C & c,const D & d,const E & 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
RevokeAll()138 void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
139
empty()140 bool empty() const { return !weak_factory_.HasWeakPtrs(); }
141
142 protected:
143 template <class Method, class Params>
144 class RunnableMethod : public CancelableTask {
145 public:
RunnableMethod(const base::WeakPtr<T> & obj,Method meth,const Params & params)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
Run()157 virtual void Run() {
158 if (obj_)
159 DispatchToMethod(obj_.get(), meth_, params_);
160 }
161
Cancel()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:
DeleteTask(const T * obj)184 explicit DeleteTask(const T* obj) : obj_(obj) {
185 }
Run()186 virtual void Run() {
187 delete obj_;
188 }
Cancel()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:
ReleaseTask(const T * obj)201 explicit ReleaseTask(const T* obj) : obj_(obj) {
202 }
Run()203 virtual void Run() {
204 if (obj_)
205 obj_->Release();
206 }
Cancel()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 {
RunnableMethodTraitsRunnableMethodTraits229 RunnableMethodTraits() {
230 #ifndef NDEBUG
231 origin_thread_id_ = base::PlatformThread::CurrentId();
232 #endif
233 }
234
~RunnableMethodTraitsRunnableMethodTraits235 ~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
RetainCalleeRunnableMethodTraits244 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
ReleaseCalleeRunnableMethodTraits255 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:
RunnableMethod(T * obj,Method meth,const Params & params)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
~RunnableMethod()326 ~RunnableMethod() {
327 ReleaseCallee();
328 }
329
Run()330 virtual void Run() {
331 if (obj_)
332 DispatchToMethod(obj_, meth_, params_);
333 }
334
Cancel()335 virtual void Cancel() {
336 ReleaseCallee();
337 }
338
339 private:
ReleaseCallee()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>
NewRunnableMethod(T * object,Method 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>
NewRunnableMethod(T * object,Method method,const A & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & c,const D & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & c,const D & d,const E & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & c,const D & d,const E & e,const F & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & c,const D & d,const E & e,const F & f,const G & 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>
NewRunnableMethod(T * object,Method method,const A & a,const B & b,const C & c,const D & d,const E & e,const F & f,const G & g,const H & 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:
RunnableFunction(Function function,const Params & params)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
~RunnableFunction()454 ~RunnableFunction() {
455 }
456
Run()457 virtual void Run() {
458 if (function_)
459 DispatchToFunction(function_, params_);
460 }
461
Cancel()462 virtual void Cancel() {
463 }
464
465 private:
466 Function function_;
467 Params params_;
468 };
469
470 template <class Function>
NewRunnableFunction(Function function)471 inline CancelableTask* NewRunnableFunction(Function function) {
472 return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
473 }
474
475 template <class Function, class A>
NewRunnableFunction(Function function,const A & 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>
NewRunnableFunction(Function function,const A & a,const B & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & c,const D & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & c,const D & d,const E & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & c,const D & d,const E & e,const F & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & c,const D & d,const E & e,const F & f,const G & 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>
NewRunnableFunction(Function function,const A & a,const B & b,const C & c,const D & d,const E & e,const F & f,const G & g,const H & 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