LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - task.h (source / functions) Hit Total Coverage
Test: output.info Lines: 25 98 25.5 %
Date: 2017-07-14 16:53:18 Functions: 38 286 13.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #ifndef BASE_TASK_H_
       8             : #define BASE_TASK_H_
       9             : 
      10             : #include "base/revocable_store.h"
      11             : #include "base/tuple.h"
      12             : #include "mozilla/IndexSequence.h"
      13             : #include "mozilla/Tuple.h"
      14             : #include "nsISupportsImpl.h"
      15             : #include "nsThreadUtils.h"
      16             : 
      17             : // Helper functions so that we can call a function a pass it arguments that come
      18             : // from a Tuple.
      19             : 
      20             : namespace details {
      21             : 
      22             : // Call the given method on the given object. Arguments are passed by move
      23             : // semantics from the given tuple. If the tuple has length N, the sequence must
      24             : // be IndexSequence<0, 1, ..., N-1>.
      25             : template<size_t... Indices, class ObjT, class Method, typename... Args>
      26           0 : void CallMethod(mozilla::IndexSequence<Indices...>, ObjT* obj, Method method,
      27             :                 mozilla::Tuple<Args...>& arg)
      28             : {
      29           0 :   (obj->*method)(mozilla::Move(mozilla::Get<Indices>(arg))...);
      30           0 : }
      31             : 
      32             : // Same as above, but call a function.
      33             : template<size_t... Indices, typename Function, typename... Args>
      34           7 : void CallFunction(mozilla::IndexSequence<Indices...>, Function function,
      35             :                   mozilla::Tuple<Args...>& arg)
      36             : {
      37           7 :   (*function)(mozilla::Move(mozilla::Get<Indices>(arg))...);
      38           7 : }
      39             : 
      40             : } // namespace details
      41             : 
      42             : // Call a method on the given object. Arguments are passed by move semantics
      43             : // from the given tuple.
      44             : template<class ObjT, class Method, typename... Args>
      45           0 : void DispatchTupleToMethod(ObjT* obj, Method method, mozilla::Tuple<Args...>& arg)
      46             : {
      47           0 :   details::CallMethod(typename mozilla::IndexSequenceFor<Args...>::Type(),
      48             :                       obj, method, arg);
      49           0 : }
      50             : 
      51             : // Same as above, but call a function.
      52             : template<typename Function, typename... Args>
      53           7 : void DispatchTupleToFunction(Function function, mozilla::Tuple<Args...>& arg)
      54             : {
      55           7 :   details::CallFunction(typename mozilla::IndexSequenceFor<Args...>::Type(),
      56             :                         function, arg);
      57           7 : }
      58             : 
      59             : // Scoped Factories ------------------------------------------------------------
      60             : //
      61             : // These scoped factory objects can be used by non-refcounted objects to safely
      62             : // place tasks in a message loop.  Each factory guarantees that the tasks it
      63             : // produces will not run after the factory is destroyed.  Commonly, factories
      64             : // are declared as class members, so the class' tasks will automatically cancel
      65             : // when the class instance is destroyed.
      66             : //
      67             : // Exampe Usage:
      68             : //
      69             : // class MyClass {
      70             : //  private:
      71             : //   // This factory will be used to schedule invocations of SomeMethod.
      72             : //   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
      73             : //
      74             : //  public:
      75             : //   // It is safe to suppress warning 4355 here.
      76             : //   MyClass() : some_method_factory_(this) { }
      77             : //
      78             : //   void SomeMethod() {
      79             : //     // If this function might be called directly, you might want to revoke
      80             : //     // any outstanding runnable methods scheduled to call it.  If it's not
      81             : //     // referenced other than by the factory, this is unnecessary.
      82             : //     some_method_factory_.RevokeAll();
      83             : //     ...
      84             : //   }
      85             : //
      86             : //   void ScheduleSomeMethod() {
      87             : //     // If you'd like to only only have one pending task at a time, test for
      88             : //     // |empty| before manufacturing another task.
      89             : //     if (!some_method_factory_.empty())
      90             : //       return;
      91             : //
      92             : //     // The factories are not thread safe, so always invoke on
      93             : //     // |MessageLoop::current()|.
      94             : //     MessageLoop::current()->PostDelayedTask(
      95             : //         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
      96             : //         kSomeMethodDelayMS);
      97             : //   }
      98             : // };
      99             : 
     100             : // A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from
     101             : // running after it is destroyed.
     102             : template<class TaskType>
     103             : class ScopedTaskFactory : public RevocableStore {
     104             :  public:
     105             :   ScopedTaskFactory() { }
     106             : 
     107             :   // Create a new task.
     108             :   inline TaskType* NewTask() {
     109             :     return new TaskWrapper(this);
     110             :   }
     111             : 
     112             :   class TaskWrapper : public TaskType {
     113             :    public:
     114           0 :     explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
     115             : 
     116           0 :     NS_IMETHOD Run() override {
     117           0 :       if (!revocable_.revoked())
     118           0 :         TaskType::Run();
     119           0 :       return NS_OK;
     120             :     }
     121             : 
     122           0 :     ~TaskWrapper() {
     123           0 :       NS_ASSERT_OWNINGTHREAD(TaskWrapper);
     124           0 :     }
     125             : 
     126             :    private:
     127             :     Revocable revocable_;
     128             : 
     129             :     NS_DECL_OWNINGTHREAD
     130             : 
     131             :     DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);
     132             :   };
     133             : 
     134             :  private:
     135             :   DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory);
     136             : };
     137             : 
     138             : // A ScopedRunnableMethodFactory creates runnable methods for a specified
     139             : // object.  This is particularly useful for generating callbacks for
     140             : // non-reference counted objects when the factory is a member of the object.
     141             : template<class T>
     142          13 : class ScopedRunnableMethodFactory : public RevocableStore {
     143             :  public:
     144          41 :   explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }
     145             : 
     146             :   template <class Method, typename... Elements>
     147             :   inline already_AddRefed<mozilla::Runnable>
     148           0 :   NewRunnableMethod(Method method, Elements&&... elements) {
     149             :     typedef mozilla::Tuple<typename mozilla::Decay<Elements>::Type...> ArgsTuple;
     150             :     typedef RunnableMethod<Method, ArgsTuple> Runnable;
     151             :     typedef typename ScopedTaskFactory<Runnable>::TaskWrapper TaskWrapper;
     152             : 
     153           0 :     RefPtr<TaskWrapper> task = new TaskWrapper(this);
     154           0 :     task->Init(object_, method, mozilla::MakeTuple(mozilla::Forward<Elements>(elements)...));
     155           0 :     return task.forget();
     156             :   }
     157             : 
     158             :  protected:
     159             :   template <class Method, class Params>
     160           0 :   class RunnableMethod : public mozilla::Runnable {
     161             :    public:
     162           0 :      RunnableMethod()
     163           0 :        : mozilla::Runnable("ScopedRunnableMethodFactory::RunnableMethod")
     164             :      {
     165           0 :      }
     166             : 
     167           0 :      void Init(T* obj, Method meth, Params&& params)
     168             :      {
     169           0 :        obj_ = obj;
     170           0 :        meth_ = meth;
     171           0 :        params_ = mozilla::Forward<Params>(params);
     172           0 :     }
     173             : 
     174           0 :     NS_IMETHOD Run() override {
     175           0 :       DispatchTupleToMethod(obj_, meth_, params_);
     176           0 :       return NS_OK;
     177             :     }
     178             : 
     179             :    private:
     180             :     T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
     181             :                       "external factors.") obj_;
     182             :     Method meth_;
     183             :     Params params_;
     184             : 
     185             :     DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);
     186             :   };
     187             : 
     188             :  private:
     189             :   T* object_;
     190             : 
     191             :   DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory);
     192             : };
     193             : 
     194             : // General task implementations ------------------------------------------------
     195             : 
     196             : // Task to delete an object
     197             : template<class T>
     198           0 : class DeleteTask : public mozilla::CancelableRunnable {
     199             :  public:
     200           0 :    explicit DeleteTask(T* obj)
     201             :      : mozilla::CancelableRunnable("DeleteTask")
     202           0 :      , obj_(obj)
     203             :    {
     204           0 :   }
     205           0 :   NS_IMETHOD Run() override {
     206           0 :     delete obj_;
     207           0 :     return NS_OK;
     208             :   }
     209           0 :   virtual nsresult Cancel() override {
     210           0 :     obj_ = NULL;
     211           0 :     return NS_OK;
     212             :   }
     213             :  private:
     214             :   T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
     215             :                     "external factors.") obj_;
     216             : };
     217             : 
     218             : // RunnableMethodTraits --------------------------------------------------------
     219             : //
     220             : // This traits-class is used by RunnableMethod to manage the lifetime of the
     221             : // callee object.  By default, it is assumed that the callee supports AddRef
     222             : // and Release methods.  A particular class can specialize this template to
     223             : // define other lifetime management.  For example, if the callee is known to
     224             : // live longer than the RunnableMethod object, then a RunnableMethodTraits
     225             : // struct could be defined with empty RetainCallee and ReleaseCallee methods.
     226             : 
     227             : template <class T>
     228           0 : struct RunnableMethodTraits {
     229           0 :   static void RetainCallee(T* obj) {
     230           0 :     obj->AddRef();
     231           0 :   }
     232           0 :   static void ReleaseCallee(T* obj) {
     233           0 :     obj->Release();
     234           0 :   }
     235             : };
     236             : 
     237             : // This allows using the NewRunnableMethod() functions with a const pointer
     238             : // to the callee object. See the similar support in nsRefPtr for a rationale
     239             : // of why this is reasonable.
     240             : template <class T>
     241             : struct RunnableMethodTraits<const T> {
     242             :   static void RetainCallee(const T* obj) {
     243             :     const_cast<T*>(obj)->AddRef();
     244             :   }
     245             :   static void ReleaseCallee(const  T* obj) {
     246             :     const_cast<T*>(obj)->Release();
     247             :   }
     248             : };
     249             : 
     250             : // RunnableMethod and RunnableFunction -----------------------------------------
     251             : //
     252             : // Runnable methods are a type of task that call a function on an object when
     253             : // they are run. We implement both an object and a set of NewRunnableMethod and
     254             : // NewRunnableFunction functions for convenience. These functions are
     255             : // overloaded and will infer the template types, simplifying calling code.
     256             : //
     257             : // The template definitions all use the following names:
     258             : // T                - the class type of the object you're supplying
     259             : //                    this is not needed for the Static version of the call
     260             : // Method/Function  - the signature of a pointer to the method or function you
     261             : //                    want to call
     262             : // Param            - the parameter(s) to the method, possibly packed as a Tuple
     263             : // A                - the first parameter (if any) to the method
     264             : // B                - the second parameter (if any) to the mathod
     265             : //
     266             : // Put these all together and you get an object that can call a method whose
     267             : // signature is:
     268             : //   R T::MyFunction([A[, B]])
     269             : //
     270             : // Usage:
     271             : // PostTask(NewRunnableMethod(object, &Object::method[, a[, b]])
     272             : // PostTask(NewRunnableFunction(&function[, a[, b]])
     273             : 
     274             : // RunnableMethod and NewRunnableMethod implementation -------------------------
     275             : 
     276             : template <class T, class Method, class Params>
     277             : class RunnableMethod : public mozilla::CancelableRunnable,
     278             :                        public RunnableMethodTraits<T> {
     279             :  public:
     280           0 :    RunnableMethod(T* obj, Method meth, Params&& params)
     281             :      : mozilla::CancelableRunnable("RunnableMethod")
     282             :      , obj_(obj)
     283             :      , meth_(meth)
     284           0 :      , params_(mozilla::Forward<Params>(params))
     285             :    {
     286           0 :      this->RetainCallee(obj_);
     287           0 :   }
     288           0 :   ~RunnableMethod() {
     289           0 :     ReleaseCallee();
     290           0 :   }
     291             : 
     292           0 :   NS_IMETHOD Run() override {
     293           0 :     if (obj_)
     294           0 :       DispatchTupleToMethod(obj_, meth_, params_);
     295           0 :     return NS_OK;
     296             :   }
     297             : 
     298           0 :   virtual nsresult Cancel() override {
     299           0 :     ReleaseCallee();
     300           0 :     return NS_OK;
     301             :   }
     302             : 
     303             :  private:
     304           0 :   void ReleaseCallee() {
     305           0 :     if (obj_) {
     306           0 :       RunnableMethodTraits<T>::ReleaseCallee(obj_);
     307           0 :       obj_ = nullptr;
     308             :     }
     309           0 :   }
     310             : 
     311             :   // This is owning because of the RetainCallee and ReleaseCallee calls in the
     312             :   // constructor and destructor.
     313             :   T* MOZ_OWNING_REF obj_;
     314             :   Method meth_;
     315             :   Params params_;
     316             : };
     317             : 
     318             : namespace dont_add_new_uses_of_this {
     319             : 
     320             : // Don't add new uses of this!!!!
     321             : template <class T, class Method, typename... Args>
     322             : inline already_AddRefed<mozilla::Runnable>
     323           0 : NewRunnableMethod(T* object, Method method, Args&&... args) {
     324             :   typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple;
     325             :   RefPtr<mozilla::Runnable> t =
     326           0 :     new RunnableMethod<T, Method, ArgsTuple>(object, method,
     327           0 :                                              mozilla::MakeTuple(mozilla::Forward<Args>(args)...));
     328           0 :   return t.forget();
     329             : }
     330             : 
     331             : } // namespace dont_add_new_uses_of_this
     332             : 
     333             : // RunnableFunction and NewRunnableFunction implementation ---------------------
     334             : 
     335             : template <class Function, class Params>
     336             : class RunnableFunction : public mozilla::CancelableRunnable {
     337             :  public:
     338           7 :    RunnableFunction(Function function, Params&& params)
     339             :      : mozilla::CancelableRunnable("RunnableFunction")
     340             :      , function_(function)
     341           7 :      , params_(mozilla::Forward<Params>(params))
     342             :    {
     343           7 :   }
     344             : 
     345          14 :   ~RunnableFunction() {
     346          21 :   }
     347             : 
     348           7 :   NS_IMETHOD Run() override {
     349           7 :     if (function_)
     350           7 :       DispatchTupleToFunction(function_, params_);
     351           7 :     return NS_OK;
     352             :   }
     353             : 
     354           0 :   virtual nsresult Cancel() override {
     355           0 :     function_ = nullptr;
     356           0 :     return NS_OK;
     357             :   }
     358             : 
     359             :   Function function_;
     360             :   Params params_;
     361             : };
     362             : 
     363             : template <class Function, typename... Args>
     364             : inline already_AddRefed<mozilla::CancelableRunnable>
     365           1 : NewCancelableRunnableFunction(Function function, Args&&... args) {
     366             :   typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple;
     367             :   RefPtr<mozilla::CancelableRunnable> t =
     368           1 :     new RunnableFunction<Function, ArgsTuple>(function,
     369           3 :                                               mozilla::MakeTuple(mozilla::Forward<Args>(args)...));
     370           2 :   return t.forget();
     371             : }
     372             : 
     373             : template <class Function, typename... Args>
     374             : inline already_AddRefed<mozilla::Runnable>
     375           6 : NewRunnableFunction(Function function, Args&&... args) {
     376             :   typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple;
     377             :   RefPtr<mozilla::Runnable> t =
     378           6 :     new RunnableFunction<Function, ArgsTuple>(function,
     379          18 :                                               mozilla::MakeTuple(mozilla::Forward<Args>(args)...));
     380          12 :   return t.forget();
     381             : }
     382             : 
     383             : #endif  // BASE_TASK_H_

Generated by: LCOV version 1.13