LCOV - code coverage report
Current view: directory - ipc/glue - MessagePump.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 89 5 5.6 %
Date: 2012-06-02 Functions: 12 3 25.0 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is Mozilla IPC.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  *   Ben Turner <bent.mozilla@gmail.com>.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "MessagePump.h"
      38                 : 
      39                 : #include "nsComponentManagerUtils.h"
      40                 : #include "nsServiceManagerUtils.h"
      41                 : #include "nsStringGlue.h"
      42                 : #include "nsThreadUtils.h"
      43                 : #include "nsXULAppAPI.h"
      44                 : #include "pratom.h"
      45                 : #include "prthread.h"
      46                 : 
      47                 : #include "base/logging.h"
      48                 : #include "base/scoped_nsautorelease_pool.h"
      49                 : 
      50                 : using mozilla::ipc::DoWorkRunnable;
      51                 : using mozilla::ipc::MessagePump;
      52                 : using mozilla::ipc::MessagePumpForChildProcess;
      53                 : using base::Time;
      54                 : 
      55            4258 : NS_IMPL_THREADSAFE_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
      56                 : 
      57                 : NS_IMETHODIMP
      58               0 : DoWorkRunnable::Run()
      59                 : {
      60               0 :   MessageLoop* loop = MessageLoop::current();
      61               0 :   NS_ASSERTION(loop, "Shouldn't be null!");
      62               0 :   if (loop) {
      63               0 :     bool nestableTasksAllowed = loop->NestableTasksAllowed();
      64                 : 
      65                 :     // MessageLoop::RunTask() disallows nesting, but our Frankenventloop
      66                 :     // will always dispatch DoWork() below from what looks to
      67                 :     // MessageLoop like a nested context.  So we unconditionally allow
      68                 :     // nesting here.
      69               0 :     loop->SetNestableTasksAllowed(true);
      70               0 :     loop->DoWork();
      71               0 :     loop->SetNestableTasksAllowed(nestableTasksAllowed);
      72                 :   }
      73               0 :   return NS_OK;
      74                 : }
      75                 : 
      76                 : NS_IMETHODIMP
      77               0 : DoWorkRunnable::Notify(nsITimer* aTimer)
      78                 : {
      79               0 :   MessageLoop* loop = MessageLoop::current();
      80               0 :   NS_ASSERTION(loop, "Shouldn't be null!");
      81               0 :   if (loop) {
      82               0 :     mPump->DoDelayedWork(loop);
      83                 :   }
      84               0 :   return NS_OK;
      85                 : }
      86                 : 
      87            1420 : MessagePump::MessagePump()
      88            1420 : : mThread(nsnull)
      89                 : {
      90            1420 :   mDoWorkEvent = new DoWorkRunnable(this);
      91            1420 : }
      92                 : 
      93                 : void
      94               0 : MessagePump::Run(MessagePump::Delegate* aDelegate)
      95                 : {
      96               0 :   NS_ASSERTION(keep_running_, "Quit must have been called outside of Run!");
      97               0 :   NS_ASSERTION(NS_IsMainThread(), "Called Run on the wrong thread!");
      98                 : 
      99               0 :   mThread = NS_GetCurrentThread();
     100               0 :   NS_ASSERTION(mThread, "This should never be null!");
     101                 : 
     102               0 :   mDelayedWorkTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     103               0 :   NS_ASSERTION(mDelayedWorkTimer, "Failed to create timer!");
     104                 : 
     105               0 :   base::ScopedNSAutoreleasePool autoReleasePool;
     106                 : 
     107               0 :   for (;;) {
     108               0 :     autoReleasePool.Recycle();
     109                 : 
     110               0 :     bool did_work = NS_ProcessNextEvent(mThread, false) ? true : false;
     111               0 :     if (!keep_running_)
     112               0 :       break;
     113                 : 
     114               0 :     did_work |= aDelegate->DoWork();
     115               0 :     if (!keep_running_)
     116               0 :       break;
     117                 : 
     118               0 :     did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
     119                 : 
     120               0 :     if (did_work && delayed_work_time_.is_null())
     121               0 :       mDelayedWorkTimer->Cancel();
     122                 : 
     123               0 :     if (!keep_running_)
     124               0 :       break;
     125                 : 
     126               0 :     if (did_work)
     127               0 :       continue;
     128                 : 
     129               0 :     did_work = aDelegate->DoIdleWork();
     130               0 :     if (!keep_running_)
     131               0 :       break;
     132                 : 
     133                 :     // This will either sleep or process an event.
     134               0 :     NS_ProcessNextEvent(mThread, true);
     135                 :   }
     136                 : 
     137               0 :   mDelayedWorkTimer->Cancel();
     138                 : 
     139               0 :   keep_running_ = true;
     140               0 : }
     141                 : 
     142                 : void
     143               0 : MessagePump::ScheduleWork()
     144                 : {
     145                 :   // Make sure the event loop wakes up.
     146               0 :   if (mThread) {
     147               0 :     mThread->Dispatch(mDoWorkEvent, NS_DISPATCH_NORMAL);
     148                 :   }
     149                 :   else {
     150                 :     // Some things (like xpcshell) don't use the app shell and so Run hasn't
     151                 :     // been called. We still need to wake up the main thread.
     152               0 :     NS_DispatchToMainThread(mDoWorkEvent, NS_DISPATCH_NORMAL);
     153                 :   }
     154               0 :   event_.Signal();
     155               0 : }
     156                 : 
     157                 : void
     158               0 : MessagePump::ScheduleWorkForNestedLoop()
     159                 : {
     160                 :   // This method is called when our MessageLoop has just allowed
     161                 :   // nested tasks.  In our setup, whenever that happens we know that
     162                 :   // DoWork() will be called "soon", so there's no need to pay the
     163                 :   // cost of what will be a no-op nsThread::Dispatch(mDoWorkEvent).
     164               0 : }
     165                 : 
     166                 : void
     167               0 : MessagePump::ScheduleDelayedWork(const base::Time& aDelayedTime)
     168                 : {
     169               0 :   if (!mDelayedWorkTimer) {
     170               0 :     mDelayedWorkTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     171               0 :     if (!mDelayedWorkTimer) {
     172                 :         // Called before XPCOM has started up? We can't do this correctly.
     173               0 :         NS_WARNING("Delayed task might not run!");
     174               0 :         delayed_work_time_ = aDelayedTime;
     175               0 :         return;
     176                 :     }
     177                 :   }
     178                 : 
     179               0 :   if (!delayed_work_time_.is_null()) {
     180               0 :     mDelayedWorkTimer->Cancel();
     181                 :   }
     182                 : 
     183               0 :   delayed_work_time_ = aDelayedTime;
     184                 : 
     185               0 :   base::TimeDelta delay = aDelayedTime - base::Time::Now();
     186               0 :   PRUint32 delayMS = PRUint32(delay.InMilliseconds());
     187               0 :   mDelayedWorkTimer->InitWithCallback(mDoWorkEvent, delayMS,
     188               0 :                                       nsITimer::TYPE_ONE_SHOT);
     189                 : }
     190                 : 
     191                 : void
     192               0 : MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate)
     193                 : {
     194               0 :   aDelegate->DoDelayedWork(&delayed_work_time_);
     195               0 :   if (!delayed_work_time_.is_null()) {
     196               0 :     ScheduleDelayedWork(delayed_work_time_);
     197                 :   }
     198               0 : }
     199                 : 
     200                 : #ifdef DEBUG
     201                 : namespace {
     202                 : MessagePump::Delegate* gFirstDelegate = nsnull;
     203                 : }
     204                 : #endif
     205                 : 
     206                 : void
     207               0 : MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
     208                 : {
     209               0 :   if (mFirstRun) {
     210                 : #ifdef DEBUG
     211               0 :     NS_ASSERTION(aDelegate && gFirstDelegate == nsnull, "Huh?!");
     212               0 :     gFirstDelegate = aDelegate;
     213                 : #endif
     214               0 :     mFirstRun = false;
     215               0 :     if (NS_FAILED(XRE_RunAppShell())) {
     216               0 :         NS_WARNING("Failed to run app shell?!");
     217                 :     }
     218                 : #ifdef DEBUG
     219               0 :     NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
     220               0 :     gFirstDelegate = nsnull;
     221                 : #endif
     222               0 :     return;
     223                 :   }
     224                 : 
     225                 : #ifdef DEBUG
     226               0 :   NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
     227                 : #endif
     228                 :   // Really run.
     229               0 :   mozilla::ipc::MessagePump::Run(aDelegate);
     230                 : }

Generated by: LCOV version 1.7