LCOV - code coverage report
Current view: top level - xpcom/base - nsMessageLoop.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 47 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
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             : /* 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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsMessageLoop.h"
       8             : #include "mozilla/WeakPtr.h"
       9             : #include "base/message_loop.h"
      10             : #include "base/task.h"
      11             : #include "nsIRunnable.h"
      12             : #include "nsITimer.h"
      13             : #include "nsCOMPtr.h"
      14             : #include "nsAutoPtr.h"
      15             : #include "nsComponentManagerUtils.h"
      16             : #include "nsThreadUtils.h"
      17             : 
      18             : using namespace mozilla;
      19             : 
      20             : namespace {
      21             : 
      22             : /**
      23             :  * This Task runs its nsIRunnable when Run() is called, or after
      24             :  * aEnsureRunsAfterMS milliseconds have elapsed since the object was
      25             :  * constructed.
      26             :  *
      27             :  * Note that the MessageLoop owns this object and will delete it after it calls
      28             :  * Run().  Tread lightly.
      29             :  */
      30             : class MessageLoopIdleTask
      31             :   : public Runnable
      32             :   , public SupportsWeakPtr<MessageLoopIdleTask>
      33             : {
      34             : public:
      35           0 :   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MessageLoopIdleTask)
      36             :   MessageLoopIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS);
      37             :   NS_IMETHOD Run() override;
      38             : 
      39             : private:
      40             :   nsresult Init(uint32_t aEnsureRunsAfterMS);
      41             : 
      42             :   nsCOMPtr<nsIRunnable> mTask;
      43             :   nsCOMPtr<nsITimer> mTimer;
      44             : 
      45           0 :   virtual ~MessageLoopIdleTask() {}
      46             : };
      47             : 
      48             : /**
      49             :  * This timer callback calls MessageLoopIdleTask::Run() when its timer fires.
      50             :  * (The timer can't call back into MessageLoopIdleTask directly since that's
      51             :  * not a refcounted object; it's owned by the MessageLoop.)
      52             :  *
      53             :  * We keep a weak reference to the MessageLoopIdleTask, although a raw pointer
      54             :  * should in theory suffice: When the MessageLoopIdleTask runs (right before
      55             :  * the MessageLoop deletes it), it cancels its timer.  But the weak pointer
      56             :  * saves us from worrying about an edge case somehow messing us up here.
      57             :  */
      58             : class MessageLoopTimerCallback
      59             :   : public nsITimerCallback
      60             : {
      61             : public:
      62             :   explicit MessageLoopTimerCallback(MessageLoopIdleTask* aTask);
      63             : 
      64             :   NS_DECL_ISUPPORTS
      65             :   NS_DECL_NSITIMERCALLBACK
      66             : 
      67             : private:
      68             :   WeakPtr<MessageLoopIdleTask> mTask;
      69             : 
      70           0 :   virtual ~MessageLoopTimerCallback() {}
      71             : };
      72             : 
      73           0 : MessageLoopIdleTask::MessageLoopIdleTask(nsIRunnable* aTask,
      74           0 :                                          uint32_t aEnsureRunsAfterMS)
      75             :   : mozilla::Runnable("MessageLoopIdleTask")
      76           0 :   , mTask(aTask)
      77             : {
      78             :   // Init() really shouldn't fail, but if it does, we schedule our runnable
      79             :   // immediately, because it's more important to guarantee that we run the task
      80             :   // eventually than it is to run the task when we're idle.
      81           0 :   nsresult rv = Init(aEnsureRunsAfterMS);
      82           0 :   if (NS_FAILED(rv)) {
      83           0 :     NS_WARNING("Running idle task early because we couldn't initialize our timer.");
      84           0 :     NS_DispatchToCurrentThread(mTask);
      85             : 
      86           0 :     mTask = nullptr;
      87           0 :     mTimer = nullptr;
      88             :   }
      89           0 : }
      90             : 
      91             : nsresult
      92           0 : MessageLoopIdleTask::Init(uint32_t aEnsureRunsAfterMS)
      93             : {
      94           0 :   mTimer = do_CreateInstance("@mozilla.org/timer;1");
      95           0 :   if (NS_WARN_IF(!mTimer)) {
      96           0 :     return NS_ERROR_UNEXPECTED;
      97             :   }
      98             : 
      99             :   RefPtr<MessageLoopTimerCallback> callback =
     100           0 :     new MessageLoopTimerCallback(this);
     101             : 
     102           0 :   return mTimer->InitWithCallback(callback, aEnsureRunsAfterMS,
     103           0 :                                   nsITimer::TYPE_ONE_SHOT);
     104             : }
     105             : 
     106             : NS_IMETHODIMP
     107           0 : MessageLoopIdleTask::Run()
     108             : {
     109             :   // Null out our pointers because if Run() was called by the timer, this
     110             :   // object will be kept alive by the MessageLoop until the MessageLoop calls
     111             :   // Run().
     112             : 
     113           0 :   if (mTimer) {
     114           0 :     mTimer->Cancel();
     115           0 :     mTimer = nullptr;
     116             :   }
     117             : 
     118           0 :   if (mTask) {
     119           0 :     mTask->Run();
     120           0 :     mTask = nullptr;
     121             :   }
     122             : 
     123           0 :   return NS_OK;
     124             : }
     125             : 
     126           0 : MessageLoopTimerCallback::MessageLoopTimerCallback(MessageLoopIdleTask* aTask)
     127           0 :   : mTask(aTask)
     128             : {
     129           0 : }
     130             : 
     131             : NS_IMETHODIMP
     132           0 : MessageLoopTimerCallback::Notify(nsITimer* aTimer)
     133             : {
     134             :   // We don't expect to hit the case when the timer fires but mTask has been
     135             :   // deleted, because mTask should cancel the timer before the mTask is
     136             :   // deleted.  But you never know...
     137           0 :   NS_WARNING_ASSERTION(mTask, "This timer shouldn't have fired.");
     138             : 
     139           0 :   if (mTask) {
     140           0 :     mTask->Run();
     141             :   }
     142           0 :   return NS_OK;
     143             : }
     144             : 
     145           0 : NS_IMPL_ISUPPORTS(MessageLoopTimerCallback, nsITimerCallback)
     146             : 
     147             : } // namespace
     148             : 
     149           0 : NS_IMPL_ISUPPORTS(nsMessageLoop, nsIMessageLoop)
     150             : 
     151             : NS_IMETHODIMP
     152           0 : nsMessageLoop::PostIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS)
     153             : {
     154             :   // The message loop owns MessageLoopIdleTask and deletes it after calling
     155             :   // Run().  Be careful...
     156             :   RefPtr<MessageLoopIdleTask> idle =
     157           0 :     new MessageLoopIdleTask(aTask, aEnsureRunsAfterMS);
     158           0 :   MessageLoop::current()->PostIdleTask(idle.forget());
     159             : 
     160           0 :   return NS_OK;
     161             : }
     162             : 
     163             : nsresult
     164           0 : nsMessageLoopConstructor(nsISupports* aOuter,
     165             :                          const nsIID& aIID,
     166             :                          void** aInstancePtr)
     167             : {
     168           0 :   if (NS_WARN_IF(aOuter)) {
     169           0 :     return NS_ERROR_NO_AGGREGATION;
     170             :   }
     171           0 :   nsISupports* messageLoop = new nsMessageLoop();
     172           0 :   return messageLoop->QueryInterface(aIID, aInstancePtr);
     173             : }

Generated by: LCOV version 1.13