• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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