LCOV - code coverage report
Current view: top level - media/mtransport - runnable_utils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 14 57 24.6 %
Date: 2017-07-14 16:53:18 Functions: 8 567 1.4 %
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=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : // Original author: ekr@rtfm.com
       8             : 
       9             : #ifndef runnable_utils_h__
      10             : #define runnable_utils_h__
      11             : 
      12             : #include "nsThreadUtils.h"
      13             : #include "mozilla/IndexSequence.h"
      14             : #include "mozilla/Move.h"
      15             : #include "mozilla/RefPtr.h"
      16             : #include "mozilla/Tuple.h"
      17             : 
      18             : // Abstract base class for all of our templates
      19             : namespace mozilla {
      20             : 
      21             : namespace detail {
      22             : 
      23             : enum RunnableResult {
      24             :   NoResult,
      25             :   ReturnsResult
      26             : };
      27             : 
      28             : static inline nsresult
      29           0 : RunOnThreadInternal(nsIEventTarget *thread, nsIRunnable *runnable, uint32_t flags)
      30             : {
      31           0 :   nsCOMPtr<nsIRunnable> runnable_ref(runnable);
      32           0 :   if (thread) {
      33             :     bool on;
      34             :     nsresult rv;
      35           0 :     rv = thread->IsOnCurrentThread(&on);
      36             : 
      37             :     // If the target thread has already shut down, we don't want to assert.
      38           0 :     if (rv != NS_ERROR_NOT_INITIALIZED) {
      39           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
      40             :     }
      41             : 
      42           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
      43             :       // we're going to destroy the runnable on this thread!
      44           0 :       return rv;
      45             :     }
      46           0 :     if (!on) {
      47           0 :       return thread->Dispatch(runnable_ref.forget(), flags);
      48             :     }
      49             :   }
      50           0 :   return runnable_ref->Run();
      51             : }
      52             : 
      53             : template<RunnableResult result>
      54           1 : class runnable_args_base : public Runnable {
      55             :  public:
      56           1 :   runnable_args_base() : Runnable("media-runnable_args_base") {}
      57             : 
      58             :   NS_IMETHOD Run() = 0;
      59             : };
      60             : 
      61             : 
      62             : template<typename R>
      63             : struct RunnableFunctionCallHelper
      64             : {
      65             :   template<typename FunType, typename... Args, size_t... Indices>
      66             :   static R apply(FunType func, Tuple<Args...>& args, IndexSequence<Indices...>)
      67             :   {
      68             :     return func(Get<Indices>(args)...);
      69             :   }
      70             : };
      71             : 
      72             : // A void specialization is needed in the case where the template instantiator
      73             : // knows we don't want to return a value, but we don't know whether the called
      74             : // function returns void or something else.
      75             : template<>
      76             : struct RunnableFunctionCallHelper<void>
      77             : {
      78             :   template<typename FunType, typename... Args, size_t... Indices>
      79           0 :   static void apply(FunType func, Tuple<Args...>& args, IndexSequence<Indices...>)
      80             :   {
      81           0 :     func(Get<Indices>(args)...);
      82           0 :   }
      83             : };
      84             : 
      85             : template<typename R>
      86             : struct RunnableMethodCallHelper
      87             : {
      88             :   template<typename Class, typename M, typename... Args, size_t... Indices>
      89           0 :   static R apply(Class obj, M method, Tuple<Args...>& args, IndexSequence<Indices...>)
      90             :   {
      91           0 :     return ((*obj).*method)(Get<Indices>(args)...);
      92             :   }
      93             : };
      94             : 
      95             : // A void specialization is needed in the case where the template instantiator
      96             : // knows we don't want to return a value, but we don't know whether the called
      97             : // method returns void or something else.
      98             : template<>
      99             : struct RunnableMethodCallHelper<void>
     100             : {
     101             :   template<typename Class, typename M, typename... Args, size_t... Indices>
     102           1 :   static void apply(Class obj, M method, Tuple<Args...>& args, IndexSequence<Indices...>)
     103             :   {
     104           1 :     ((*obj).*method)(Get<Indices>(args)...);
     105           1 :   }
     106             : };
     107             : 
     108             : }
     109             : 
     110             : template<typename FunType, typename... Args>
     111           0 : class runnable_args_func : public detail::runnable_args_base<detail::NoResult>
     112             : {
     113             : public:
     114             :   // |explicit| to pacify static analysis when there are no |args|.
     115             :   template<typename... Arguments>
     116           0 :   explicit runnable_args_func(FunType f, Arguments&&... args)
     117           0 :     : mFunc(f), mArgs(Forward<Arguments>(args)...)
     118           0 :   {}
     119             : 
     120           0 :   NS_IMETHOD Run() {
     121           0 :     detail::RunnableFunctionCallHelper<void>::apply(mFunc, mArgs, typename IndexSequenceFor<Args...>::Type());
     122           0 :     return NS_OK;
     123             :   }
     124             : 
     125             : private:
     126             :   FunType mFunc;
     127             :   Tuple<Args...> mArgs;
     128             : };
     129             : 
     130             : template<typename FunType, typename... Args>
     131             : runnable_args_func<FunType, typename mozilla::Decay<Args>::Type...>*
     132           0 : WrapRunnableNM(FunType f, Args&&... args)
     133             : {
     134           0 :   return new runnable_args_func<FunType, typename mozilla::Decay<Args>::Type...>(f, Forward<Args>(args)...);
     135             : }
     136             : 
     137             : template<typename Ret, typename FunType, typename... Args>
     138             : class runnable_args_func_ret : public detail::runnable_args_base<detail::ReturnsResult>
     139             : {
     140             : public:
     141             :   runnable_args_func_ret(Ret* ret, FunType f, Args&&... args)
     142             :     : mReturn(ret), mFunc(f), mArgs(Forward<Args>(args)...)
     143             :   {}
     144             : 
     145             :   NS_IMETHOD Run() {
     146             :     *mReturn = detail::RunnableFunctionCallHelper<Ret>::apply(mFunc, mArgs, typename IndexSequenceFor<Args...>::Type());
     147             :     return NS_OK;
     148             :   }
     149             : 
     150             : private:
     151             :   Ret* mReturn;
     152             :   FunType mFunc;
     153             :   Tuple<Args...> mArgs;
     154             : };
     155             : 
     156             : template<typename R, typename FunType, typename... Args>
     157             : runnable_args_func_ret<R, FunType, Args...>*
     158             : WrapRunnableNMRet(R* ret, FunType f, Args... args)
     159             : {
     160             :   return new runnable_args_func_ret<R, FunType, Args...>(ret, f, Move(args)...);
     161             : }
     162             : 
     163             : template<typename Class, typename M, typename... Args>
     164           3 : class runnable_args_memfn : public detail::runnable_args_base<detail::NoResult>
     165             : {
     166             : public:
     167           1 :   runnable_args_memfn(Class obj, M method, Args&&... args)
     168           1 :     : mObj(obj), mMethod(method), mArgs(Forward<Args>(args)...)
     169           1 :   {}
     170             : 
     171           1 :   NS_IMETHOD Run() {
     172           1 :     detail::RunnableMethodCallHelper<void>::apply(mObj, mMethod, mArgs, typename IndexSequenceFor<Args...>::Type());
     173           1 :     return NS_OK;
     174             :   }
     175             : 
     176             : private:
     177             :   Class mObj;
     178             :   M mMethod;
     179             :   Tuple<Args...> mArgs;
     180             : };
     181             : 
     182             : template<typename Class, typename M, typename... Args>
     183             : runnable_args_memfn<Class, M, Args...>*
     184           1 : WrapRunnable(Class obj, M method, Args... args)
     185             : {
     186           2 :   return new runnable_args_memfn<Class, M, Args...>(obj, method, Move(args)...);
     187             : }
     188             : 
     189             : template<typename Ret, typename Class, typename M, typename... Args>
     190           0 : class runnable_args_memfn_ret : public detail::runnable_args_base<detail::ReturnsResult>
     191             : {
     192             : public:
     193           0 :   runnable_args_memfn_ret(Ret* ret, Class obj, M method, Args... args)
     194           0 :     : mReturn(ret), mObj(obj), mMethod(method), mArgs(Forward<Args>(args)...)
     195           0 :   {}
     196             : 
     197           0 :   NS_IMETHOD Run() {
     198           0 :     *mReturn = detail::RunnableMethodCallHelper<Ret>::apply(mObj, mMethod, mArgs, typename IndexSequenceFor<Args...>::Type());
     199           0 :     return NS_OK;
     200             :   }
     201             : 
     202             : private:
     203             :   Ret* mReturn;
     204             :   Class mObj;
     205             :   M mMethod;
     206             :   Tuple<Args...> mArgs;
     207             : };
     208             : 
     209             : template<typename R, typename Class, typename M, typename... Args>
     210             : runnable_args_memfn_ret<R, Class, M, Args...>*
     211           0 : WrapRunnableRet(R* ret, Class obj, M method, Args... args)
     212             : {
     213           0 :   return new runnable_args_memfn_ret<R, Class, M, Args...>(ret, obj, method, Move(args)...);
     214             : }
     215             : 
     216           0 : static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, detail::runnable_args_base<detail::NoResult> *runnable, uint32_t flags) {
     217           0 :   return detail::RunOnThreadInternal(thread, static_cast<nsIRunnable *>(runnable), flags);
     218             : }
     219             : 
     220             : static inline nsresult
     221             : RUN_ON_THREAD(nsIEventTarget *thread, detail::runnable_args_base<detail::ReturnsResult> *runnable)
     222             : {
     223             :   return detail::RunOnThreadInternal(thread, static_cast<nsIRunnable *>(runnable), NS_DISPATCH_SYNC);
     224             : }
     225             : 
     226             : #ifdef DEBUG
     227             : #define ASSERT_ON_THREAD(t) do {                \
     228             :     if (t) {                                    \
     229             :       bool on;                                    \
     230             :       nsresult rv;                                \
     231             :       rv = t->IsOnCurrentThread(&on);             \
     232             :       MOZ_ASSERT(NS_SUCCEEDED(rv));               \
     233             :       MOZ_ASSERT(on);                             \
     234             :     }                                           \
     235             :   } while(0)
     236             : #else
     237             : #define ASSERT_ON_THREAD(t)
     238             : #endif
     239             : 
     240             : template <class T>
     241           0 : class DispatchedRelease : public detail::runnable_args_base<detail::NoResult> {
     242             : public:
     243           0 :   explicit DispatchedRelease(already_AddRefed<T>& ref) : ref_(ref) {}
     244             : 
     245           0 :   NS_IMETHOD Run() {
     246           0 :     ref_ = nullptr;
     247           0 :     return NS_OK;
     248             :   }
     249             : private:
     250             :   RefPtr<T> ref_;
     251             : };
     252             : 
     253             : template <typename T>
     254           0 : DispatchedRelease<T>* WrapRelease(already_AddRefed<T>&& ref)
     255             : {
     256           0 :   return new DispatchedRelease<T>(ref);
     257             : }
     258             : 
     259             : } /* namespace mozilla */
     260             : 
     261             : #endif

Generated by: LCOV version 1.13