Backout of bug 443874: Need a hook for thread creation and destruction in thread pool
authorDave Townsend <dtownsend@oxymoronical.com>
Fri, 25 Jul 2008 10:21:04 -0400
changeset 16207 29af572a67ba8909adae342fb5c4baa08b43c0ef
parent 16206 753d440883fd9b3a4186358dab4a649e8baadab5
child 16208 8fda6cca7d249d78779aa441879ee5e965709153
push idunknown
push userunknown
push dateunknown
bugs443874
milestone1.9.1a2pre
Backout of bug 443874: Need a hook for thread creation and destruction in thread pool Removes the following changesets: 01e24ad20f35 ebf77231b06e f4b859edddd2 22201dfdb1f3 f8762f56712f 2c6f51bf3bed c8ac37904c16
xpcom/tests/Makefile.in
xpcom/tests/TestThreadPoolListener.cpp
xpcom/threads/nsIThreadPool.idl
xpcom/threads/nsThreadPool.cpp
xpcom/threads/nsThreadPool.h
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -74,17 +74,16 @@ CPPSRCS		= \
 		TestObserverService.cpp \
 		TestServMgr.cpp \
 		TestAutoPtr.cpp \
 		TestVersionComparator.cpp \
 		TestTextFormatter.cpp \
 		TestPipe.cpp \
 		TestRegistrationOrder.cpp \
 		TestProxies.cpp \
-		TestThreadPoolListener.cpp \
 		TestTimers.cpp \
 		$(NULL)
 
 ifndef MOZ_ENABLE_LIBXUL
 CPPSRCS += \
 		TestArray.cpp \
 		TestTArray.cpp \
 		TestAtoms.cpp \
@@ -106,19 +105,16 @@ endif
 ifndef MOZILLA_INTERNAL_API
 CPPSRCS += \
 		TestStringAPI.cpp \
 		$(NULL)
 endif
 
 SIMPLE_PROGRAMS	= $(CPPSRCS:.cpp=$(BIN_SUFFIX))
 
-# Make sure we have symbols in case we need to debug these.
-MOZ_DEBUG_SYMBOLS = 1
-
 include $(topsrcdir)/config/config.mk
 
 ifndef MOZILLA_INTERNAL_API
 LIBS +=	$(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX)
 endif
 
 LIBS		+= \
 		$(XPCOM_LIBS) \
@@ -140,17 +136,16 @@ CPP_UNIT_TESTS = \
   TestCOMPtrEq \
   TestFactory \
   TestHashtables \
   TestID \
   TestObserverService \
   TestPipe \
   TestServMgr \
   TestTextFormatter \
-  TestThreadPoolListener \
   TestTimers \
   $(NULL)
 
 ifndef MOZ_ENABLE_LIBXUL
 CPP_UNIT_TESTS += \
   TestArray \
   TestAutoLock \
   TestCRT \
deleted file mode 100644
--- a/xpcom/tests/TestThreadPoolListener.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Thread Pool Listener Test Code.
- *
- * The Initial Developer of the Original Code is
- *   Ben Turner <bent.mozilla@gmail.com>.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "TestHarness.h"
-
-#include "nsIThread.h"
-#include "nsIThreadPool.h"
-
-#include "nsAutoLock.h"
-#include "nsThreadUtils.h"
-#include "nsXPCOMCIDInternal.h"
-#include "pratom.h"
-#include "prinrval.h"
-#include "prmon.h"
-#include "prthread.h"
-
-#define NUMBER_OF_THREADS 4
-
-// One hour... because test boxes can be slow!
-#define IDLE_THREAD_TIMEOUT 3600000
-
-static nsIThread** gCreatedThreadList = nsnull;
-static nsIThread** gShutDownThreadList = nsnull;
-
-static PRMonitor* gMonitor = nsnull;
-
-static PRBool gAllRunnablesPosted = PR_FALSE;
-static PRBool gAllThreadsCreated = PR_FALSE;
-static PRBool gAllThreadsShutDown = PR_FALSE;
-
-#ifdef DEBUG
-#define TEST_ASSERTION(_test, _msg) \
-    NS_ASSERTION(_test, _msg);
-#else
-#define TEST_ASSERTION(_test, _msg) \
-  PR_BEGIN_MACRO \
-    if (!(_test)) { \
-      NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_test, __FILE__, __LINE__); \
-    } \
-  PR_END_MACRO
-#endif
-
-class Listener : public nsIThreadPoolListener
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSITHREADPOOLLISTENER
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(Listener, nsIThreadPoolListener)
-
-NS_IMETHODIMP
-Listener::OnThreadCreated()
-{
-  nsCOMPtr<nsIThread> current(do_GetCurrentThread());
-  TEST_ASSERTION(current, "Couldn't get current thread!");
-
-  nsAutoMonitor mon(gMonitor);
-
-  while (!gAllRunnablesPosted) {
-    mon.Wait();
-  }
-
-  for (PRUint32 i = 0; i < NUMBER_OF_THREADS; i++) {
-    nsIThread* thread = gCreatedThreadList[i];
-    TEST_ASSERTION(thread != current, "Saw the same thread twice!");
-
-    if (!thread) {
-      gCreatedThreadList[i] = current;
-      if (i == (NUMBER_OF_THREADS - 1)) {
-        gAllThreadsCreated = PR_TRUE;
-        mon.NotifyAll();
-      }
-      return NS_OK;
-    }
-  }
-
-  TEST_ASSERTION(PR_FALSE, "Too many threads!");
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-Listener::OnThreadShuttingDown()
-{
-  nsCOMPtr<nsIThread> current(do_GetCurrentThread());
-  TEST_ASSERTION(current, "Couldn't get current thread!");
-
-  nsAutoMonitor mon(gMonitor);
-
-  for (PRUint32 i = 0; i < NUMBER_OF_THREADS; i++) {
-    nsIThread* thread = gShutDownThreadList[i];
-    TEST_ASSERTION(thread != current, "Saw the same thread twice!");
-
-    if (!thread) {
-      gShutDownThreadList[i] = current;
-      if (i == (NUMBER_OF_THREADS - 1)) {
-        gAllThreadsShutDown = PR_TRUE;
-        mon.NotifyAll();
-      }
-      return NS_OK;
-    }
-  }
-
-  TEST_ASSERTION(PR_FALSE, "Too many threads!");
-  return NS_ERROR_FAILURE;
-}
-
-class AutoCreateAndDestroyMonitor
-{
-public:
-  AutoCreateAndDestroyMonitor(PRMonitor** aMonitorPtr)
-  : mMonitorPtr(aMonitorPtr) {
-    *aMonitorPtr = nsAutoMonitor::NewMonitor("TestThreadPoolListener::AutoMon");
-    TEST_ASSERTION(*aMonitorPtr, "Out of memory!");
-  }
-
-  ~AutoCreateAndDestroyMonitor() {
-    if (*mMonitorPtr) {
-      nsAutoMonitor::DestroyMonitor(*mMonitorPtr);
-      *mMonitorPtr = nsnull;
-    }
-  }
-
-private:
-  PRMonitor** mMonitorPtr;
-};
-
-int main(int argc, char** argv)
-{
-#ifndef XP_WIN
-  ScopedXPCOM xpcom("ThreadPoolListener");
-  NS_ENSURE_FALSE(xpcom.failed(), 1);
-
-  nsIThread* createdThreadList[NUMBER_OF_THREADS] = { nsnull };
-  gCreatedThreadList = createdThreadList;
-
-  nsIThread* shutDownThreadList[NUMBER_OF_THREADS] = { nsnull };
-  gShutDownThreadList = shutDownThreadList;
-
-  AutoCreateAndDestroyMonitor newMon(&gMonitor);
-  NS_ENSURE_TRUE(gMonitor, 1);
-
-  nsresult rv;
-  nsCOMPtr<nsIThreadPool> pool =
-    do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  rv = pool->SetThreadLimit(NUMBER_OF_THREADS);
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  rv = pool->SetIdleThreadLimit(NUMBER_OF_THREADS);
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  rv = pool->SetIdleThreadTimeout(IDLE_THREAD_TIMEOUT);
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  nsCOMPtr<nsIThreadPoolListener> listener = new Listener();
-  NS_ENSURE_TRUE(listener, 1);
-
-  rv = pool->SetListener(listener);
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  {
-    nsAutoMonitor mon(gMonitor);
-
-    for (PRUint32 i = 0; i < NUMBER_OF_THREADS; i++) {
-      nsCOMPtr<nsIRunnable> runnable = new nsRunnable();
-      NS_ENSURE_TRUE(runnable, 1);
-
-      rv = pool->Dispatch(runnable, NS_DISPATCH_NORMAL);
-      NS_ENSURE_SUCCESS(rv, 1);
-    }
-
-    gAllRunnablesPosted = PR_TRUE;
-    mon.NotifyAll();
-  }
-
-  {
-    nsAutoMonitor mon(gMonitor);
-    while (!gAllThreadsCreated) {
-      mon.Wait();
-    }
-  }
-
-  rv = pool->Shutdown();
-  NS_ENSURE_SUCCESS(rv, 1);
-
-  {
-    nsAutoMonitor mon(gMonitor);
-    while (!gAllThreadsShutDown) {
-      mon.Wait();
-    }
-  }
-
-  for (PRUint32 i = 0; i < NUMBER_OF_THREADS; i++) {
-    nsIThread* created = gCreatedThreadList[i];
-    NS_ENSURE_TRUE(created, 1);
-
-    PRBool match = PR_FALSE;
-    for (PRUint32 j = 0; j < NUMBER_OF_THREADS; j++) {
-      nsIThread* destroyed = gShutDownThreadList[j];
-      NS_ENSURE_TRUE(destroyed, 1);
-
-      if (destroyed == created) {
-        match = PR_TRUE;
-        break;
-      }
-    }
-
-    NS_ENSURE_TRUE(match, 1);
-  }
-#endif
-  return 0;
-}
--- a/xpcom/threads/nsIThreadPool.idl
+++ b/xpcom/threads/nsIThreadPool.idl
@@ -33,38 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIEventTarget.idl"
 
-[scriptable, uuid(ef194cab-3f86-4b61-b132-e5e96a79e5d1)]
-interface nsIThreadPoolListener : nsISupports
-{
-  /**
-   * Called when a new thread is created by the thread pool. The notification
-   * happens on the newly-created thread.
-   */
-  void onThreadCreated();
-
-  /**
-   * Called when a thread is about to be destroyed by the thread pool. The
-   * notification happens on the thread that is about to be destroyed.
-   */
-  void onThreadShuttingDown();
-};
-
 /**
  * An interface to a thread pool.  A thread pool creates a limited number of
  * anonymous (unnamed) worker threads.  An event dispatched to the thread pool
  * will be run on the next available worker thread.
  */
-[scriptable, uuid(61cc5ac4-3f58-49f4-9d1c-8eaa73373de1)]
+[scriptable, uuid(394c29f0-225f-487f-86d3-4c259da76cab)]
 interface nsIThreadPool : nsIEventTarget
 {
   /**
    * Shutdown the thread pool.  This method may not be executed from any thread
    * in the thread pool.  Instead, it is meant to be executed from another
    * thread (usually the thread that created this thread pool).  When this
    * function returns, the thread pool and all of its threads will be shutdown,
    * and it will no longer be possible to dispatch tasks to the thread pool.
@@ -81,26 +65,9 @@ interface nsIThreadPool : nsIEventTarget
    */
   attribute unsigned long idleThreadLimit;
 
   /**
    * Get/set the amount of time in milliseconds before an idle thread is
    * destroyed.
    */
   attribute unsigned long idleThreadTimeout;
-
-  /**
-   * An optional listener that will be notified when a thread is created or
-   * destroyed in the course of the thread pool's operation.
-   *
-   * A listener will only receive notifications about threads created after the
-   * listener is set so it is recommended that the consumer set the listener
-   * before dispatching the first event. A listener that receives an
-   * onThreadCreated() notification is guaranteed to always receive the
-   * corresponding onThreadShuttingDown() notification.
-   *
-   * The thread pool takes ownership of the listener and releases it when the
-   * shutdown() method is called. Threads created after the listener is set will
-   * also take ownership of the listener so that the listener will be kept alive
-   * long enough to receive the guaranteed onThreadShuttingDown() notification.
-   */
-  attribute nsIThreadPoolListener listener;
 };
--- a/xpcom/threads/nsThreadPool.cpp
+++ b/xpcom/threads/nsThreadPool.cpp
@@ -157,26 +157,16 @@ nsThreadPool::Run()
   nsCOMPtr<nsIThread> current;
   nsThreadManager::get()->GetCurrentThread(getter_AddRefs(current));
 
   PRBool shutdownThreadOnExit = PR_FALSE;
   PRBool exitThread = PR_FALSE;
   PRBool wasIdle = PR_FALSE;
   PRIntervalTime idleSince;
 
-  nsCOMPtr<nsIThreadPoolListener> listener;
-  {
-    nsAutoMonitor mon(mEvents.Monitor());
-    listener = mListener;
-  }
-
-  if (listener) {
-    listener->OnThreadCreated();
-  }
-
   do {
     nsCOMPtr<nsIRunnable> event;
     {
       nsAutoMonitor mon(mEvents.Monitor());
       if (!mEvents.GetPendingEvent(getter_AddRefs(event))) {
         PRIntervalTime now     = PR_IntervalNow();
         PRIntervalTime timeout = PR_MillisecondsToInterval(mIdleThreadTimeout);
 
@@ -215,22 +205,18 @@ nsThreadPool::Run()
       }
     }
     if (event) {
       LOG(("THRD-P(%p) running [%p]\n", this, event.get()));
       event->Run();
     }
   } while (!exitThread);
 
-  if (shutdownThreadOnExit) {
-    if (listener) {
-      listener->OnThreadShuttingDown();
-    }
+  if (shutdownThreadOnExit)
     ShutdownThread(current);
-  }
 
   LOG(("THRD-P(%p) leave\n", this));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThreadPool::Dispatch(nsIRunnable *event, PRUint32 flags)
 {
@@ -266,28 +252,22 @@ nsThreadPool::IsOnCurrentThread(PRBool *
   *result = PR_FALSE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThreadPool::Shutdown()
 {
   nsCOMArray<nsIThread> threads;
-  nsCOMPtr<nsIThreadPoolListener> listener;
   {
     nsAutoMonitor mon(mEvents.Monitor());
     mShutdown = PR_TRUE;
     mon.NotifyAll();
 
     threads.AppendObjects(mThreads);
-
-    // Swap in a null listener so that we release the listener at the end of
-    // this method. The listener will be kept alive as long as the other threads
-    // that were created when it was set.
-    mListener.swap(listener);
   }
 
   // It's important that we shutdown the threads while outside the event queue
   // monitor.  Otherwise, we could end up dead-locking.  The threads will take
   // care of removing themselves from mThreads as they exit.
 
   for (PRInt32 i = 0; i < threads.Count(); ++i)
     threads[i]->Shutdown();
@@ -341,27 +321,8 @@ nsThreadPool::GetIdleThreadTimeout(PRUin
 NS_IMETHODIMP
 nsThreadPool::SetIdleThreadTimeout(PRUint32 value)
 {
   nsAutoMonitor mon(mEvents.Monitor());
   mIdleThreadTimeout = value;
   mon.NotifyAll();  // wake up threads so they observe this change
   return NS_OK;
 }
-
-NS_IMETHODIMP
-nsThreadPool::GetListener(nsIThreadPoolListener** aListener)
-{
-  nsAutoMonitor mon(mEvents.Monitor());
-  NS_IF_ADDREF(*aListener = mListener);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsThreadPool::SetListener(nsIThreadPoolListener* aListener)
-{
-  nsCOMPtr<nsIThreadPoolListener> swappedListener(aListener);
-  {
-    nsAutoMonitor mon(mEvents.Monitor());
-    mListener.swap(swappedListener);
-  }
-  return NS_OK;
-}
--- a/xpcom/threads/nsThreadPool.h
+++ b/xpcom/threads/nsThreadPool.h
@@ -39,17 +39,16 @@
 #ifndef nsThreadPool_h__
 #define nsThreadPool_h__
 
 #include "nsIThreadPool.h"
 #include "nsIThread.h"
 #include "nsIRunnable.h"
 #include "nsEventQueue.h"
 #include "nsCOMArray.h"
-#include "nsCOMPtr.h"
 
 class nsThreadPool : public nsIThreadPool, public nsIRunnable
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEVENTTARGET
   NS_DECL_NSITHREADPOOL
   NS_DECL_NSIRUNNABLE
@@ -63,17 +62,16 @@ private:
   nsresult PutEvent(nsIRunnable *event);
 
   nsCOMArray<nsIThread> mThreads;
   nsEventQueue          mEvents;
   PRUint32              mThreadLimit;
   PRUint32              mIdleThreadLimit;
   PRUint32              mIdleThreadTimeout;
   PRUint32              mIdleCount;
-  nsCOMPtr<nsIThreadPoolListener> mListener;
   PRBool                mShutdown;
 };
 
 #define NS_THREADPOOL_CLASSNAME "nsThreadPool"
 #define NS_THREADPOOL_CID                          \
 { /* 547ec2a8-315e-4ec4-888e-6e4264fe90eb */       \
   0x547ec2a8,                                      \
   0x315e,                                          \