// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_TASK_H_ #define BASE_TASK_H_ #pragma once #include "base/base_api.h" #include "base/memory/raw_scoped_refptr_mismatch_checker.h" #include "base/memory/weak_ptr.h" #include "base/tracked.h" #include "base/tuple.h" // Task ------------------------------------------------------------------------ // // A task is a generic runnable thingy, usually used for running code on a // different thread or for scheduling future tasks off of the message loop. class BASE_API Task : public tracked_objects::Tracked { public: Task(); virtual ~Task(); // Tasks are automatically deleted after Run is called. virtual void Run() = 0; }; class BASE_API CancelableTask : public Task { public: CancelableTask(); virtual ~CancelableTask(); // Not all tasks support cancellation. virtual void Cancel() = 0; }; // Scoped Factories ------------------------------------------------------------ // // These scoped factory objects can be used by non-refcounted objects to safely // place tasks in a message loop. Each factory guarantees that the tasks it // produces will not run after the factory is destroyed. Commonly, factories // are declared as class members, so the class' tasks will automatically cancel // when the class instance is destroyed. // // Exampe Usage: // // class MyClass { // private: // // This factory will be used to schedule invocations of SomeMethod. // ScopedRunnableMethodFactory<MyClass> some_method_factory_; // // public: // // It is safe to suppress warning 4355 here. // MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { } // // void SomeMethod() { // // If this function might be called directly, you might want to revoke // // any outstanding runnable methods scheduled to call it. If it's not // // referenced other than by the factory, this is unnecessary. // some_method_factory_.RevokeAll(); // ... // } // // void ScheduleSomeMethod() { // // If you'd like to only only have one pending task at a time, test for // // |empty| before manufacturing another task. // if (!some_method_factory_.empty()) // return; // // // The factories are not thread safe, so always invoke on // // |MessageLoop::current()|. // MessageLoop::current()->PostDelayedTask( // FROM_HERE, // some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod), // kSomeMethodDelayMS); // } // }; // A ScopedRunnableMethodFactory creates runnable methods for a specified // object. This is particularly useful for generating callbacks for // non-reference counted objects when the factory is a member of the object. template<class T> class ScopedRunnableMethodFactory { public: explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) { } template <class Method> inline CancelableTask* NewRunnableMethod(Method method) { return new RunnableMethod<Method, Tuple0>( weak_factory_.GetWeakPtr(), method, MakeTuple()); } template <class Method, class A> inline CancelableTask* NewRunnableMethod(Method method, const A& a) { return new RunnableMethod<Method, Tuple1<A> >( weak_factory_.GetWeakPtr(), method, MakeTuple(a)); } template <class Method, class A, class B> inline CancelableTask* NewRunnableMethod(Method method, const A& a, const B& b) { return new RunnableMethod<Method, Tuple2<A, B> >( weak_factory_.GetWeakPtr(), method, MakeTuple(a, b)); } template <class Method, class A, class B, class C> inline CancelableTask* NewRunnableMethod(Method method, const A& a, const B& b, const C& c) { return new RunnableMethod<Method, Tuple3<A, B, C> >( weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c)); } template <class Method, class A, class B, class C, class D> inline CancelableTask* NewRunnableMethod(Method method, const A& a, const B& b, const C& c, const D& d) { return new RunnableMethod<Method, Tuple4<A, B, C, D> >( weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d)); } template <class Method, class A, class B, class C, class D, class E> inline CancelableTask* NewRunnableMethod(Method method, const A& a, const B& b, const C& c, const D& d, const E& e) { return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >( weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e)); } void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } bool empty() const { return !weak_factory_.HasWeakPtrs(); } protected: template <class Method, class Params> class RunnableMethod : public CancelableTask { public: RunnableMethod(const base::WeakPtr<T>& obj, Method meth, const Params& params) : obj_(obj), meth_(meth), params_(params) { COMPILE_ASSERT( (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), badscopedrunnablemethodparams); } virtual void Run() { if (obj_) DispatchToMethod(obj_.get(), meth_, params_); } virtual void Cancel() { obj_.reset(); } private: base::WeakPtr<T> obj_; Method meth_; Params params_; DISALLOW_COPY_AND_ASSIGN(RunnableMethod); }; private: base::WeakPtrFactory<T> weak_factory_; }; // General task implementations ------------------------------------------------ // Task to delete an object template<class T> class DeleteTask : public CancelableTask { public: explicit DeleteTask(const T* obj) : obj_(obj) { } virtual void Run() { delete obj_; } virtual void Cancel() { obj_ = NULL; } private: const T* obj_; }; // Task to Release() an object template<class T> class ReleaseTask : public CancelableTask { public: explicit ReleaseTask(const T* obj) : obj_(obj) { } virtual void Run() { if (obj_) obj_->Release(); } virtual void Cancel() { obj_ = NULL; } private: const T* obj_; }; // RunnableMethodTraits -------------------------------------------------------- // // This traits-class is used by RunnableMethod to manage the lifetime of the // callee object. By default, it is assumed that the callee supports AddRef // and Release methods. A particular class can specialize this template to // define other lifetime management. For example, if the callee is known to // live longer than the RunnableMethod object, then a RunnableMethodTraits // struct could be defined with empty RetainCallee and ReleaseCallee methods. // // The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way // for declaring a RunnableMethodTraits that disables refcounting. template <class T> struct RunnableMethodTraits { RunnableMethodTraits() { #ifndef NDEBUG origin_thread_id_ = base::PlatformThread::CurrentId(); #endif } ~RunnableMethodTraits() { #ifndef NDEBUG // If destroyed on a separate thread, then we had better have been using // thread-safe reference counting! if (origin_thread_id_ != base::PlatformThread::CurrentId()) DCHECK(T::ImplementsThreadSafeReferenceCounting()); #endif } void RetainCallee(T* obj) { #ifndef NDEBUG // Catch NewRunnableMethod being called in an object's constructor. This // isn't safe since the method can be invoked before the constructor // completes, causing the object to be deleted. obj->AddRef(); obj->Release(); #endif obj->AddRef(); } void ReleaseCallee(T* obj) { obj->Release(); } private: #ifndef NDEBUG base::PlatformThreadId origin_thread_id_; #endif }; // Convenience macro for declaring a RunnableMethodTraits that disables // refcounting of a class. This is useful if you know that the callee // will outlive the RunnableMethod object and thus do not need the ref counts. // // The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the // global namespace scope. Example: // // namespace foo { // class Bar { // ... // }; // } // namespace foo // // DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar); // // This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the // class. #define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \ template <> \ struct RunnableMethodTraits<TypeName> { \ void RetainCallee(TypeName* manager) {} \ void ReleaseCallee(TypeName* manager) {} \ } // RunnableMethod and RunnableFunction ----------------------------------------- // // Runnable methods are a type of task that call a function on an object when // they are run. We implement both an object and a set of NewRunnableMethod and // NewRunnableFunction functions for convenience. These functions are // overloaded and will infer the template types, simplifying calling code. // // The template definitions all use the following names: // T - the class type of the object you're supplying // this is not needed for the Static version of the call // Method/Function - the signature of a pointer to the method or function you // want to call // Param - the parameter(s) to the method, possibly packed as a Tuple // A - the first parameter (if any) to the method // B - the second parameter (if any) to the method // // Put these all together and you get an object that can call a method whose // signature is: // R T::MyFunction([A[, B]]) // // Usage: // PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]]) // PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]]) // RunnableMethod and NewRunnableMethod implementation ------------------------- template <class T, class Method, class Params> class RunnableMethod : public CancelableTask { public: RunnableMethod(T* obj, Method meth, const Params& params) : obj_(obj), meth_(meth), params_(params) { traits_.RetainCallee(obj_); COMPILE_ASSERT( (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), badrunnablemethodparams); } ~RunnableMethod() { ReleaseCallee(); } virtual void Run() { if (obj_) DispatchToMethod(obj_, meth_, params_); } virtual void Cancel() { ReleaseCallee(); } private: void ReleaseCallee() { T* obj = obj_; obj_ = NULL; if (obj) traits_.ReleaseCallee(obj); } T* obj_; Method meth_; Params params_; RunnableMethodTraits<T> traits_; }; template <class T, class Method> inline CancelableTask* NewRunnableMethod(T* object, Method method) { return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple()); } template <class T, class Method, class A> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) { return new RunnableMethod<T, Method, Tuple1<A> >(object, method, MakeTuple(a)); } template <class T, class Method, class A, class B> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a, const B& b) { return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method, MakeTuple(a, b)); } template <class T, class Method, class A, class B, class C> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a, const B& b, const C& c) { return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method, MakeTuple(a, b, c)); } template <class T, class Method, class A, class B, class C, class D> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a, const B& b, const C& c, const D& d) { return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method, MakeTuple(a, b, c, d)); } template <class T, class Method, class A, class B, class C, class D, class E> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a, const B& b, const C& c, const D& d, const E& e) { return new RunnableMethod<T, Method, Tuple5<A, B, C, D, E> >(object, method, MakeTuple(a, b, c, d, e)); } template <class T, class Method, class A, class B, class C, class D, class E, class F> inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a, const B& b, const C& c, const D& d, const E& e, const F& f) { return new RunnableMethod<T, Method, Tuple6<A, B, C, D, E, F> >(object, method, MakeTuple(a, b, c, d, e, f)); } template <class T, class Method, class A, class B, class C, class D, class E, class F, class G> inline CancelableTask* 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) { return new RunnableMethod<T, Method, Tuple7<A, B, C, D, E, F, G> >(object, method, MakeTuple(a, b, c, d, e, f, g)); } template <class T, class Method, class A, class B, class C, class D, class E, class F, class G, class H> inline CancelableTask* 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) { return new RunnableMethod<T, Method, Tuple8<A, B, C, D, E, F, G, H> >(object, method, MakeTuple(a, b, c, d, e, f, g, h)); } // RunnableFunction and NewRunnableFunction implementation --------------------- template <class Function, class Params> class RunnableFunction : public CancelableTask { public: RunnableFunction(Function function, const Params& params) : function_(function), params_(params) { COMPILE_ASSERT( (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), badrunnablefunctionparams); } ~RunnableFunction() { } virtual void Run() { if (function_) DispatchToFunction(function_, params_); } virtual void Cancel() { } private: Function function_; Params params_; }; template <class Function> inline CancelableTask* NewRunnableFunction(Function function) { return new RunnableFunction<Function, Tuple0>(function, MakeTuple()); } template <class Function, class A> inline CancelableTask* NewRunnableFunction(Function function, const A& a) { return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a)); } template <class Function, class A, class B> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b) { return new RunnableFunction<Function, Tuple2<A, B> >(function, MakeTuple(a, b)); } template <class Function, class A, class B, class C> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b, const C& c) { return new RunnableFunction<Function, Tuple3<A, B, C> >(function, MakeTuple(a, b, c)); } template <class Function, class A, class B, class C, class D> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b, const C& c, const D& d) { return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function, MakeTuple(a, b, c, d)); } template <class Function, class A, class B, class C, class D, class E> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b, const C& c, const D& d, const E& e) { return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function, MakeTuple(a, b, c, d, e)); } template <class Function, class A, class B, class C, class D, class E, class F> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b, const C& c, const D& d, const E& e, const F& f) { return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function, MakeTuple(a, b, c, d, e, f)); } template <class Function, class A, class B, class C, class D, class E, class F, class G> inline CancelableTask* NewRunnableFunction(Function function, const A& a, const B& b, const C& c, const D& d, const E& e, const F& f, const G& g) { return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function, MakeTuple(a, b, c, d, e, f, g)); } template <class Function, class A, class B, class C, class D, class E, class F, class G, class H> inline CancelableTask* 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) { return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >( function, MakeTuple(a, b, c, d, e, f, g, h)); } #endif // BASE_TASK_H_