LCOV - code coverage report
Current view: directory - xpcom/threads - LazyIdleThread.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 220 138 62.7 %
Date: 2012-06-02 Functions: 26 18 69.2 %

       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                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Indexed Database.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * The Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Ben Turner <bent.mozilla@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "LazyIdleThread.h"
      41                 : 
      42                 : #include "nsIObserverService.h"
      43                 : 
      44                 : #include "nsComponentManagerUtils.h"
      45                 : #include "nsServiceManagerUtils.h"
      46                 : #include "nsThreadUtils.h"
      47                 : #include "mozilla/Services.h"
      48                 : 
      49                 : #ifdef DEBUG
      50                 : #define ASSERT_OWNING_THREAD()                                                 \
      51                 :   PR_BEGIN_MACRO                                                               \
      52                 :     nsIThread* currentThread = NS_GetCurrentThread();                          \
      53                 :     if (currentThread) {                                                       \
      54                 :       nsCOMPtr<nsISupports> current(do_QueryInterface(currentThread));         \
      55                 :       nsCOMPtr<nsISupports> test(do_QueryInterface(mOwningThread));            \
      56                 :       NS_ASSERTION(current == test, "Wrong thread!");                          \
      57                 :     }                                                                          \
      58                 :   PR_END_MACRO
      59                 : #else
      60                 : #define ASSERT_OWNING_THREAD() /* nothing */
      61                 : #endif
      62                 : 
      63                 : namespace mozilla {
      64                 : 
      65              54 : LazyIdleThread::LazyIdleThread(PRUint32 aIdleTimeoutMS,
      66                 :                                ShutdownMethod aShutdownMethod,
      67                 :                                nsIObserver* aIdleObserver)
      68                 : : mMutex("LazyIdleThread::mMutex"),
      69                 :   mOwningThread(NS_GetCurrentThread()),
      70                 :   mIdleObserver(aIdleObserver),
      71                 :   mQueuedRunnables(nsnull),
      72                 :   mIdleTimeoutMS(aIdleTimeoutMS),
      73                 :   mPendingEventCount(0),
      74                 :   mIdleNotificationCount(0),
      75                 :   mShutdownMethod(aShutdownMethod),
      76                 :   mShutdown(false),
      77                 :   mThreadIsShuttingDown(false),
      78              54 :   mIdleTimeoutEnabled(true)
      79                 : {
      80              54 :   NS_ASSERTION(mOwningThread, "This should never fail!");
      81              54 : }
      82                 : 
      83             108 : LazyIdleThread::~LazyIdleThread()
      84                 : {
      85              54 :   ASSERT_OWNING_THREAD();
      86                 : 
      87              54 :   Shutdown();
      88              54 : }
      89                 : 
      90                 : void
      91               0 : LazyIdleThread::SetWeakIdleObserver(nsIObserver* aObserver)
      92                 : {
      93               0 :   ASSERT_OWNING_THREAD();
      94                 : 
      95               0 :   if (mShutdown) {
      96               0 :     NS_WARN_IF_FALSE(!aObserver,
      97                 :                      "Setting an observer after Shutdown was called!");
      98               0 :     return;
      99                 :   }
     100                 : 
     101               0 :   mIdleObserver = aObserver;
     102                 : }
     103                 : 
     104                 : void
     105               0 : LazyIdleThread::DisableIdleTimeout()
     106                 : {
     107               0 :   ASSERT_OWNING_THREAD();
     108               0 :   if (!mIdleTimeoutEnabled) {
     109               0 :     return;
     110                 :   }
     111               0 :   mIdleTimeoutEnabled = false;
     112                 : 
     113               0 :   if (mIdleTimer && NS_FAILED(mIdleTimer->Cancel())) {
     114               0 :     NS_WARNING("Failed to cancel timer!");
     115                 :   }
     116                 : 
     117               0 :   MutexAutoLock lock(mMutex);
     118                 : 
     119                 :   // Pretend we have a pending event to keep the idle timer from firing.
     120               0 :   NS_ASSERTION(mPendingEventCount < PR_UINT32_MAX, "Way too many!");
     121               0 :   mPendingEventCount++;
     122                 : }
     123                 : 
     124                 : void
     125               0 : LazyIdleThread::EnableIdleTimeout()
     126                 : {
     127               0 :   ASSERT_OWNING_THREAD();
     128               0 :   if (mIdleTimeoutEnabled) {
     129               0 :     return;
     130                 :   }
     131               0 :   mIdleTimeoutEnabled = true;
     132                 : 
     133                 :   {
     134               0 :     MutexAutoLock lock(mMutex);
     135                 : 
     136               0 :     NS_ASSERTION(mPendingEventCount, "Mismatched calls to observer methods!");
     137               0 :     --mPendingEventCount;
     138                 :   }
     139                 : 
     140               0 :   if (mThread) {
     141               0 :     nsCOMPtr<nsIRunnable> runnable(new nsRunnable());
     142               0 :     if (NS_FAILED(Dispatch(runnable, NS_DISPATCH_NORMAL))) {
     143               0 :       NS_WARNING("Failed to dispatch!");
     144                 :     }
     145                 :   }
     146                 : }
     147                 : 
     148                 : void
     149             138 : LazyIdleThread::PreDispatch()
     150                 : {
     151             276 :   MutexAutoLock lock(mMutex);
     152                 : 
     153             138 :   NS_ASSERTION(mPendingEventCount < PR_UINT32_MAX, "Way too many!");
     154             138 :   mPendingEventCount++;
     155             138 : }
     156                 : 
     157                 : nsresult
     158              84 : LazyIdleThread::EnsureThread()
     159                 : {
     160              84 :   ASSERT_OWNING_THREAD();
     161                 : 
     162              84 :   if (mShutdown) {
     163               0 :     return NS_ERROR_UNEXPECTED;
     164                 :   }
     165                 : 
     166              84 :   if (mThread) {
     167              30 :     return NS_OK;
     168                 :   }
     169                 : 
     170              54 :   NS_ASSERTION(!mPendingEventCount, "Shouldn't have events yet!");
     171              54 :   NS_ASSERTION(!mIdleNotificationCount, "Shouldn't have idle events yet!");
     172              54 :   NS_ASSERTION(!mIdleTimer, "Should have killed this long ago!");
     173              54 :   NS_ASSERTION(!mThreadIsShuttingDown, "Should have cleared that!");
     174                 : 
     175                 :   nsresult rv;
     176                 : 
     177              54 :   if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
     178                 :     nsCOMPtr<nsIObserverService> obs =
     179               0 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
     180               0 :     NS_ENSURE_SUCCESS(rv, rv);
     181                 : 
     182               0 :     rv = obs->AddObserver(this, "xpcom-shutdown-threads", false);
     183               0 :     NS_ENSURE_SUCCESS(rv, rv);
     184                 :   }
     185                 : 
     186              54 :   mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
     187              54 :   NS_ENSURE_TRUE(mIdleTimer, NS_ERROR_FAILURE);
     188                 : 
     189                 :   nsCOMPtr<nsIRunnable> runnable =
     190             108 :     NS_NewRunnableMethod(this, &LazyIdleThread::InitThread);
     191              54 :   NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
     192                 : 
     193              54 :   rv = NS_NewThread(getter_AddRefs(mThread), runnable);
     194              54 :   NS_ENSURE_SUCCESS(rv, rv);
     195                 : 
     196              54 :   return NS_OK;
     197                 : }
     198                 : 
     199                 : void
     200              54 : LazyIdleThread::InitThread()
     201                 : {
     202                 :   // Happens on mThread but mThread may not be set yet...
     203                 : 
     204             108 :   nsCOMPtr<nsIThreadInternal> thread(do_QueryInterface(NS_GetCurrentThread()));
     205              54 :   NS_ASSERTION(thread, "This should always succeed!");
     206                 : 
     207              54 :   if (NS_FAILED(thread->SetObserver(this))) {
     208               0 :     NS_WARNING("Failed to set thread observer!");
     209                 :   }
     210              54 : }
     211                 : 
     212                 : void
     213              54 : LazyIdleThread::CleanupThread()
     214                 : {
     215             108 :   nsCOMPtr<nsIThreadInternal> thread(do_QueryInterface(NS_GetCurrentThread()));
     216              54 :   NS_ASSERTION(thread, "This should always succeed!");
     217                 : 
     218              54 :   if (NS_FAILED(thread->SetObserver(nsnull))) {
     219               0 :     NS_WARNING("Failed to set thread observer!");
     220                 :   }
     221                 : 
     222             108 :   MutexAutoLock lock(mMutex);
     223                 : 
     224              54 :   NS_ASSERTION(!mThreadIsShuttingDown, "Shouldn't be true ever!");
     225              54 :   mThreadIsShuttingDown = true;
     226              54 : }
     227                 : 
     228                 : void
     229              80 : LazyIdleThread::ScheduleTimer()
     230                 : {
     231              80 :   ASSERT_OWNING_THREAD();
     232                 : 
     233                 :   bool shouldSchedule;
     234                 :   {
     235             160 :     MutexAutoLock lock(mMutex);
     236                 : 
     237              80 :     NS_ASSERTION(mIdleNotificationCount, "Should have at least one!");
     238              80 :     --mIdleNotificationCount;
     239                 : 
     240              80 :     shouldSchedule = !mIdleNotificationCount && !mPendingEventCount;
     241                 :   }
     242                 : 
     243              80 :   if (NS_FAILED(mIdleTimer->Cancel())) {
     244               0 :     NS_WARNING("Failed to cancel timer!");
     245                 :   }
     246                 : 
     247             160 :   if (shouldSchedule &&
     248              80 :       NS_FAILED(mIdleTimer->InitWithCallback(this, mIdleTimeoutMS,
     249                 :                                              nsITimer::TYPE_ONE_SHOT))) {
     250               0 :     NS_WARNING("Failed to schedule timer!");
     251                 :   }
     252              80 : }
     253                 : 
     254                 : nsresult
     255             108 : LazyIdleThread::ShutdownThread()
     256                 : {
     257             108 :   ASSERT_OWNING_THREAD();
     258                 : 
     259                 :   // Before calling Shutdown() on the real thread we need to put a queue in
     260                 :   // place in case a runnable is posted to the thread while it's in the
     261                 :   // process of shutting down. This will be our queue.
     262             216 :   nsAutoTArray<nsCOMPtr<nsIRunnable>, 10> queuedRunnables;
     263                 : 
     264                 :   nsresult rv;
     265                 : 
     266             108 :   if (mThread) {
     267              54 :     if (mShutdownMethod == AutomaticShutdown && NS_IsMainThread()) {
     268                 :       nsCOMPtr<nsIObserverService> obs =
     269               0 :         mozilla::services::GetObserverService();
     270               0 :       NS_WARN_IF_FALSE(obs, "Failed to get observer service!");
     271                 : 
     272               0 :       if (obs &&
     273               0 :           NS_FAILED(obs->RemoveObserver(this, "xpcom-shutdown-threads"))) {
     274               0 :         NS_WARNING("Failed to remove observer!");
     275                 :       }
     276                 :     }
     277                 : 
     278              54 :     if (mIdleObserver) {
     279                 :       mIdleObserver->Observe(static_cast<nsIThread*>(this), IDLE_THREAD_TOPIC,
     280               0 :                              nsnull);
     281                 :     }
     282                 : 
     283                 : #ifdef DEBUG
     284                 :     {
     285             108 :       MutexAutoLock lock(mMutex);
     286              54 :       NS_ASSERTION(!mThreadIsShuttingDown, "Huh?!");
     287                 :     }
     288                 : #endif
     289                 : 
     290                 :     nsCOMPtr<nsIRunnable> runnable =
     291             108 :       NS_NewRunnableMethod(this, &LazyIdleThread::CleanupThread);
     292              54 :     NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
     293                 : 
     294              54 :     PreDispatch();
     295                 : 
     296              54 :     rv = mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
     297              54 :     NS_ENSURE_SUCCESS(rv, rv);
     298                 : 
     299                 :     // Put the temporary queue in place before calling Shutdown().
     300              54 :     mQueuedRunnables = &queuedRunnables;
     301                 : 
     302              54 :     if (NS_FAILED(mThread->Shutdown())) {
     303               0 :       NS_ERROR("Failed to shutdown the thread!");
     304                 :     }
     305                 : 
     306                 :     // Now unset the queue.
     307              54 :     mQueuedRunnables = nsnull;
     308                 : 
     309              54 :     mThread = nsnull;
     310                 : 
     311                 :     {
     312             162 :       MutexAutoLock lock(mMutex);
     313                 : 
     314              54 :       NS_ASSERTION(!mPendingEventCount, "Huh?!");
     315              54 :       NS_ASSERTION(!mIdleNotificationCount, "Huh?!");
     316              54 :       NS_ASSERTION(mThreadIsShuttingDown, "Huh?!");
     317              54 :       mThreadIsShuttingDown = false;
     318                 :     }
     319                 :   }
     320                 : 
     321             108 :   if (mIdleTimer) {
     322              54 :     rv = mIdleTimer->Cancel();
     323              54 :     NS_ENSURE_SUCCESS(rv, rv);
     324                 : 
     325              54 :     mIdleTimer = nsnull;
     326                 :   }
     327                 : 
     328                 :   // If our temporary queue has any runnables then we need to dispatch them.
     329             108 :   if (queuedRunnables.Length()) {
     330                 :     // If the thread manager has gone away then these runnables will never run.
     331               0 :     if (mShutdown) {
     332               0 :       NS_ERROR("Runnables dispatched to LazyIdleThread will never run!");
     333               0 :       return NS_OK;
     334                 :     }
     335                 : 
     336                 :     // Re-dispatch the queued runnables.
     337               0 :     for (PRUint32 index = 0; index < queuedRunnables.Length(); index++) {
     338               0 :       nsCOMPtr<nsIRunnable> runnable;
     339               0 :       runnable.swap(queuedRunnables[index]);
     340               0 :       NS_ASSERTION(runnable, "Null runnable?!");
     341                 : 
     342               0 :       if (NS_FAILED(Dispatch(runnable, NS_DISPATCH_NORMAL))) {
     343               0 :         NS_ERROR("Failed to re-dispatch queued runnable!");
     344                 :       }
     345                 :     }
     346                 :   }
     347                 : 
     348             108 :   return NS_OK;
     349                 : }
     350                 : 
     351                 : void
     352              54 : LazyIdleThread::SelfDestruct()
     353                 : {
     354              54 :   NS_ASSERTION(mRefCnt == 1, "Bad refcount!");
     355              54 :   delete this;
     356              54 : }
     357                 : 
     358             860 : NS_IMPL_THREADSAFE_ADDREF(LazyIdleThread)
     359                 : 
     360                 : NS_IMETHODIMP_(nsrefcnt)
     361             860 : LazyIdleThread::Release()
     362                 : {
     363             860 :   nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
     364             860 :   NS_LOG_RELEASE(this, count, "LazyIdleThread");
     365                 : 
     366             860 :   if (!count) {
     367                 :     // Stabilize refcount.
     368              54 :     mRefCnt = 1;
     369                 : 
     370                 :     nsCOMPtr<nsIRunnable> runnable =
     371             108 :       NS_NewNonOwningRunnableMethod(this, &LazyIdleThread::SelfDestruct);
     372              54 :     NS_WARN_IF_FALSE(runnable, "Couldn't make runnable!");
     373                 : 
     374              54 :     if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
     375              54 :       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     376                 :       // The only way this could fail is if we're in shutdown, and in that case
     377                 :       // threads should have been joined already. Deleting here isn't dangerous
     378                 :       // anymore because we won't spin the event loop waiting to join the
     379                 :       // thread.
     380              54 :       SelfDestruct();
     381                 :     }
     382                 :   }
     383                 : 
     384             860 :   return count;
     385                 : }
     386                 : 
     387             227 : NS_IMPL_THREADSAFE_QUERY_INTERFACE5(LazyIdleThread, nsIThread,
     388                 :                                                     nsIEventTarget,
     389                 :                                                     nsITimerCallback,
     390                 :                                                     nsIThreadObserver,
     391                 :                                                     nsIObserver)
     392                 : 
     393                 : NS_IMETHODIMP
     394              84 : LazyIdleThread::Dispatch(nsIRunnable* aEvent,
     395                 :                          PRUint32 aFlags)
     396                 : {
     397              84 :   ASSERT_OWNING_THREAD();
     398                 : 
     399                 :   // LazyIdleThread can't always support synchronous dispatch currently.
     400              84 :   NS_ENSURE_TRUE(aFlags == NS_DISPATCH_NORMAL, NS_ERROR_NOT_IMPLEMENTED);
     401                 : 
     402                 :   // If our thread is shutting down then we can't actually dispatch right now.
     403                 :   // Queue this runnable for later.
     404              84 :   if (UseRunnableQueue()) {
     405               0 :     mQueuedRunnables->AppendElement(aEvent);
     406               0 :     return NS_OK;
     407                 :   }
     408                 : 
     409              84 :   nsresult rv = EnsureThread();
     410              84 :   NS_ENSURE_SUCCESS(rv, rv);
     411                 : 
     412              84 :   PreDispatch();
     413                 : 
     414              84 :   return mThread->Dispatch(aEvent, aFlags);
     415                 : }
     416                 : 
     417                 : NS_IMETHODIMP
     418             152 : LazyIdleThread::IsOnCurrentThread(bool* aIsOnCurrentThread)
     419                 : {
     420             152 :   if (mThread) {
     421             152 :     return mThread->IsOnCurrentThread(aIsOnCurrentThread);
     422                 :   }
     423                 : 
     424               0 :   *aIsOnCurrentThread = false;
     425               0 :   return NS_OK;
     426                 : }
     427                 : 
     428                 : NS_IMETHODIMP
     429               0 : LazyIdleThread::GetPRThread(PRThread** aPRThread)
     430                 : {
     431               0 :   if (mThread) {
     432               0 :     return mThread->GetPRThread(aPRThread);
     433                 :   }
     434                 : 
     435               0 :   *aPRThread = nsnull;
     436               0 :   return NS_ERROR_NOT_AVAILABLE;
     437                 : }
     438                 : 
     439                 : NS_IMETHODIMP
     440             108 : LazyIdleThread::Shutdown()
     441                 : {
     442             108 :   ASSERT_OWNING_THREAD();
     443                 : 
     444             108 :   mShutdown = true;
     445                 : 
     446             108 :   nsresult rv = ShutdownThread();
     447             108 :   NS_ASSERTION(!mThread, "Should have destroyed this by now!");
     448                 : 
     449             108 :   mIdleObserver = nsnull;
     450                 : 
     451             108 :   NS_ENSURE_SUCCESS(rv, rv);
     452                 : 
     453             108 :   return NS_OK;
     454                 : }
     455                 : 
     456                 : NS_IMETHODIMP
     457               0 : LazyIdleThread::HasPendingEvents(bool* aHasPendingEvents)
     458                 : {
     459                 :   // This is only supposed to be called from the thread itself so it's not
     460                 :   // implemented here.
     461               0 :   NS_NOTREACHED("Shouldn't ever call this!");
     462               0 :   return NS_ERROR_UNEXPECTED;
     463                 : }
     464                 : 
     465                 : NS_IMETHODIMP
     466               0 : LazyIdleThread::ProcessNextEvent(bool aMayWait,
     467                 :                                  bool* aEventWasProcessed)
     468                 : {
     469                 :   // This is only supposed to be called from the thread itself so it's not
     470                 :   // implemented here.
     471               0 :   NS_NOTREACHED("Shouldn't ever call this!");
     472               0 :   return NS_ERROR_UNEXPECTED;
     473                 : }
     474                 : 
     475                 : NS_IMETHODIMP
     476               0 : LazyIdleThread::Notify(nsITimer* aTimer)
     477                 : {
     478               0 :   ASSERT_OWNING_THREAD();
     479                 : 
     480                 :   {
     481               0 :     MutexAutoLock lock(mMutex);
     482                 : 
     483               0 :     if (mPendingEventCount || mIdleNotificationCount) {
     484                 :       // Another event was scheduled since this timer was set. Don't do
     485                 :       // anything and wait for the timer to fire again.
     486               0 :       return NS_OK;
     487                 :     }
     488                 :   }
     489                 : 
     490               0 :   nsresult rv = ShutdownThread();
     491               0 :   NS_ENSURE_SUCCESS(rv, rv);
     492                 : 
     493               0 :   return NS_OK;
     494                 : }
     495                 : 
     496                 : NS_IMETHODIMP
     497             111 : LazyIdleThread::OnDispatchedEvent(nsIThreadInternal* /*aThread */)
     498                 : {
     499             111 :   NS_ASSERTION(NS_GetCurrentThread() == mOwningThread, "Wrong thread!");
     500             111 :   return NS_OK;
     501                 : }
     502                 : 
     503                 : NS_IMETHODIMP
     504             138 : LazyIdleThread::OnProcessNextEvent(nsIThreadInternal* /* aThread */,
     505                 :                                    bool /* aMayWait */,
     506                 :                                    PRUint32 /* aRecursionDepth */)
     507                 : {
     508             138 :   return NS_OK;
     509                 : }
     510                 : 
     511                 : NS_IMETHODIMP
     512             138 : LazyIdleThread::AfterProcessNextEvent(nsIThreadInternal* /* aThread */,
     513                 :                                       PRUint32 /* aRecursionDepth */)
     514                 : {
     515                 :   bool shouldNotifyIdle;
     516                 :   {
     517             276 :     MutexAutoLock lock(mMutex);
     518                 : 
     519             138 :     NS_ASSERTION(mPendingEventCount, "Mismatched calls to observer methods!");
     520             138 :     --mPendingEventCount;
     521                 : 
     522             138 :     if (mThreadIsShuttingDown) {
     523                 :       // We're shutting down, no need to fire any timer.
     524              54 :       return NS_OK;
     525                 :     }
     526                 : 
     527              84 :     shouldNotifyIdle = !mPendingEventCount;
     528              84 :     if (shouldNotifyIdle) {
     529              80 :       NS_ASSERTION(mIdleNotificationCount < PR_UINT32_MAX, "Way too many!");
     530              80 :       mIdleNotificationCount++;
     531                 :     }
     532                 :   }
     533                 : 
     534              84 :   if (shouldNotifyIdle) {
     535                 :     nsCOMPtr<nsIRunnable> runnable =
     536             160 :       NS_NewRunnableMethod(this, &LazyIdleThread::ScheduleTimer);
     537              80 :     NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
     538                 : 
     539              80 :     nsresult rv = mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
     540              80 :     NS_ENSURE_SUCCESS(rv, rv);
     541                 :   }
     542                 : 
     543              84 :   return NS_OK;
     544                 : }
     545                 : 
     546                 : NS_IMETHODIMP
     547               0 : LazyIdleThread::Observe(nsISupports* /* aSubject */,
     548                 :                         const char*  aTopic,
     549                 :                         const PRUnichar* /* aData */)
     550                 : {
     551               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     552               0 :   NS_ASSERTION(mShutdownMethod == AutomaticShutdown,
     553                 :                "Should not receive notifications if not AutomaticShutdown!");
     554               0 :   NS_ASSERTION(!strcmp("xpcom-shutdown-threads", aTopic), "Bad topic!");
     555                 : 
     556               0 :   Shutdown();
     557               0 :   return NS_OK;
     558                 : }
     559                 : 
     560                 : } // namespace mozilla

Generated by: LCOV version 1.7