Relanding bug 326777, r=bsmedberg, sr=jst

This commit is contained in:
bzbarsky@mit.edu 2007-07-10 17:57:17 -07:00
parent bf0bcff1f1
commit 3b90c5c518
5 changed files with 68 additions and 1 deletions

View File

@ -50,8 +50,12 @@
#include "jsfun.h"
#include "jsobj.h"
#include "jsscript.h"
#include "nsThreadUtilsInternal.h"
NS_IMPL_THREADSAFE_ISUPPORTS2(nsXPConnect,nsIXPConnect,nsISupportsWeakReference)
NS_IMPL_THREADSAFE_ISUPPORTS3(nsXPConnect,
nsIXPConnect,
nsISupportsWeakReference,
nsIThreadObserver)
nsXPConnect* nsXPConnect::gSelf = nsnull;
JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE;
@ -286,6 +290,10 @@ nsXPConnect::GetXPConnect()
// Initial extra ref to keep the singleton alive
// balanced by explicit call to ReleaseXPConnectSingleton()
NS_ADDREF(gSelf);
if (NS_FAILED(NS_SetGlobalThreadObserver(gSelf))) {
NS_RELEASE(gSelf);
// Fall through to returning null
}
}
}
return gSelf;
@ -307,6 +315,7 @@ nsXPConnect::ReleaseXPConnectSingleton()
nsXPConnect* xpc = gSelf;
if(xpc)
{
NS_SetGlobalThreadObserver(nsnull);
#ifdef XPC_TOOLS_SUPPORT
if(xpc->mProfiler)
@ -2014,6 +2023,31 @@ nsXPConnect::FlagSystemFilenamePrefix(const char *aFilenamePrefix)
return NS_OK;
}
NS_IMETHODIMP
nsXPConnect::OnProcessNextEvent(nsIThreadInternal *aThread, PRBool aMayWait,
PRUint32 aRecursionDepth)
{
// Push a null JSContext so that we don't see any script during
// event processing.
NS_ENSURE_STATE(mContextStack);
return mContextStack->Push(nsnull);
}
NS_IMETHODIMP
nsXPConnect::AfterProcessNextEvent(nsIThreadInternal *aThread,
PRUint32 aRecursionDepth)
{
NS_ENSURE_STATE(mContextStack);
return mContextStack->Pop(nsnull);
}
NS_IMETHODIMP
nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
{
NS_NOTREACHED("Why tell us?");
return NS_ERROR_UNEXPECTED;
}
#ifdef DEBUG
/* These are here to be callable from a debugger */
JS_BEGIN_EXTERN_C

View File

@ -126,6 +126,8 @@
#include "nsIXPCToolsProfiler.h"
#endif
#include "nsIThreadInternal.h"
#ifdef XPC_IDISPATCH_SUPPORT
// This goop was added because of EXCEPINFO in ThrowCOMError
// This include is here, because it needs to occur before the undefines below
@ -426,6 +428,7 @@ const PRBool OBJ_IS_NOT_GLOBAL = PR_FALSE;
struct JSObjectRefcounts;
class nsXPConnect : public nsIXPConnect,
public nsIThreadObserver,
public nsSupportsWeakReference,
public nsCycleCollectionLanguageRuntime,
public nsCycleCollectionParticipant
@ -434,6 +437,7 @@ public:
// all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCONNECT
NS_DECL_NSITHREADOBSERVER
// non-interface implementation
public:

View File

@ -69,6 +69,7 @@ CPPSRCS = \
EXPORTS = \
nsProcess.h \
nsEventQueue.h \
nsThreadUtilsInternal.h \
$(NULL)
XPIDLSRCS = \

View File

@ -44,6 +44,7 @@
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "prlog.h"
#include "nsThreadUtilsInternal.h"
#ifdef PR_LOGGING
static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
@ -52,6 +53,8 @@ static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
NS_DECL_CI_INTERFACE_GETTER(nsThread)
nsIThreadObserver* nsThread::sGlobalObserver;
//-----------------------------------------------------------------------------
// Because we do not have our own nsIFactory, we have to implement nsIClassInfo
// somewhat manually.
@ -464,6 +467,10 @@ nsThread::ProcessNextEvent(PRBool mayWait, PRBool *result)
NS_ENSURE_STATE(PR_GetCurrentThread() == mThread);
if (sGlobalObserver)
sGlobalObserver->OnProcessNextEvent(this, mayWait && !ShuttingDown(),
mRunningEvent);
nsCOMPtr<nsIThreadObserver> obs = mObserver;
if (obs)
obs->OnProcessNextEvent(this, mayWait && !ShuttingDown(), mRunningEvent);
@ -489,6 +496,9 @@ nsThread::ProcessNextEvent(PRBool mayWait, PRBool *result)
if (obs)
obs->AfterProcessNextEvent(this, mRunningEvent);
if (sGlobalObserver)
sGlobalObserver->AfterProcessNextEvent(this, mRunningEvent);
return rv;
}
@ -618,3 +628,18 @@ nsThreadSyncDispatch::Run()
}
return NS_OK;
}
nsresult
NS_SetGlobalThreadObserver(nsIThreadObserver* aObserver)
{
if (aObserver && nsThread::sGlobalObserver) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!NS_IsMainThread()) {
return NS_ERROR_UNEXPECTED;
}
nsThread::sGlobalObserver = aObserver;
return NS_OK;
}

View File

@ -72,6 +72,9 @@ public:
// nsIThreadManager::NewThread.
PRBool ShutdownRequired() { return mShutdownRequired; }
// The global thread observer
static nsIThreadObserver* sGlobalObserver;
private:
friend class nsThreadShutdownEvent;