Make thread locking less stupid.

This commit is contained in:
pedemont%us.ibm.com 2005-03-14 21:18:53 +00:00
parent 3b76f41e91
commit 727e6e4ffc
4 changed files with 51 additions and 38 deletions

View File

@ -1301,25 +1301,32 @@ JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
// Due to Java's garbage collection, this finalize statement may get called
// after FreeJavaGlobals(). So check to make sure that everything is still
// initialized.
if (gJavaXPCOMMonitor) {
nsAutoMonitor mon(gJavaXPCOMMonitor);
if (gJavaXPCOMLock) {
nsAutoLock lock(gJavaXPCOMLock);
// Get native XPCOM instance
void* xpcom_obj;
nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
if (NS_SUCCEEDED(rv)) {
JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
#ifdef DEBUG_JAVAXPCOM
xpcom_addr = NS_REINTERPRET_CAST(PRUint32, inst->GetInstance());
#endif
nsIID* iid;
rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
// If may be possible for the lock to be acquired here when FreeGlobals is
// in the middle of running. If so, then this thread will sleep until
// FreeGlobals releases its lock. At that point, we resume this thread
// here, but JavaXPCOM may no longer be initialized. So we need to check
// that everything is legit after acquiring the lock.
if (gJavaXPCOMInitialized) {
// Get native XPCOM instance
void* xpcom_obj;
nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
if (NS_SUCCEEDED(rv)) {
rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
nsMemory::Free(iid);
JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
#ifdef DEBUG_JAVAXPCOM
xpcom_addr = NS_REINTERPRET_CAST(PRUint32, inst->GetInstance());
#endif
nsIID* iid;
rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
if (NS_SUCCEEDED(rv)) {
rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
nsMemory::Free(iid);
}
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
delete inst;
}
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
delete inst;
}
}

View File

@ -89,7 +89,8 @@ jmethodID proxyToStringMID = nsnull;
NativeToJavaProxyMap* gNativeToJavaProxyMap = nsnull;
JavaToXPTCStubMap* gJavaToXPTCStubMap = nsnull;
PRMonitor* gJavaXPCOMMonitor = nsnull;
PRBool gJavaXPCOMInitialized = PR_FALSE;
PRLock* gJavaXPCOMLock = nsnull;
/******************************
@ -98,7 +99,7 @@ PRMonitor* gJavaXPCOMMonitor = nsnull;
PRBool
InitializeJavaGlobals(JNIEnv *env)
{
if (gJavaXPCOMMonitor)
if (gJavaXPCOMInitialized)
return PR_TRUE;
jclass clazz;
@ -244,7 +245,8 @@ InitializeJavaGlobals(JNIEnv *env)
goto init_error;
}
gJavaXPCOMMonitor = nsAutoMonitor::NewMonitor("Javaconnect Monitor");
gJavaXPCOMLock = PR_NewLock();
gJavaXPCOMInitialized = PR_TRUE;
return PR_TRUE;
init_error:
@ -260,7 +262,13 @@ init_error:
void
FreeJavaGlobals(JNIEnv* env)
{
PR_EnterMonitor(gJavaXPCOMMonitor);
PR_Lock(gJavaXPCOMLock);
// null out global lock so no one else can use it
PRLock* tempLock = gJavaXPCOMLock;
gJavaXPCOMLock = nsnull;
gJavaXPCOMInitialized = PR_FALSE;
// Free the mappings first, since that process depends on some of the Java
// globals that are freed later.
@ -325,9 +333,8 @@ FreeJavaGlobals(JNIEnv* env)
xpcomJavaProxyClass = nsnull;
}
PR_ExitMonitor(gJavaXPCOMMonitor);
nsAutoMonitor::DestroyMonitor(gJavaXPCOMMonitor);
gJavaXPCOMMonitor = nsnull;
PR_Unlock(tempLock);
PR_DestroyLock(tempLock);
}
@ -402,7 +409,8 @@ DestroyJavaProxyMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
nsresult
NativeToJavaProxyMap::Destroy(JNIEnv* env)
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
// This is only called from FreeGlobals(), which already holds the lock.
// nsAutoLock lock(gJavaXPCOMLock);
PL_DHashTableEnumerate(mHashTable, DestroyJavaProxyMappingEnum, env);
PL_DHashTableDestroy(mHashTable);
@ -415,7 +423,7 @@ nsresult
NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
const nsIID& aIID, jobject aProxy)
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
nsAutoLock lock(gJavaXPCOMLock);
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
aXPCOMObject,
@ -450,7 +458,7 @@ NativeToJavaProxyMap::Find(JNIEnv* env, nsISupports* aNativeObject,
if (!aResult)
return NS_ERROR_FAILURE;
nsAutoMonitor mon(gJavaXPCOMMonitor);
nsAutoLock lock(gJavaXPCOMLock);
*aResult = nsnull;
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
@ -485,7 +493,8 @@ nsresult
NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
const nsIID& aIID)
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
// This is only called from finalizeProxy(), which already holds the lock.
// nsAutoLock lock(gJavaXPCOMLock);
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
aNativeObject,
@ -557,7 +566,8 @@ DestroyXPTCMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
nsresult
JavaToXPTCStubMap::Destroy()
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
// This is only called from FreeGlobals(), which already holds the lock.
// nsAutoLock lock(gJavaXPCOMLock);
PL_DHashTableEnumerate(mHashTable, DestroyXPTCMappingEnum, nsnull);
PL_DHashTableDestroy(mHashTable);
@ -569,7 +579,7 @@ JavaToXPTCStubMap::Destroy()
nsresult
JavaToXPTCStubMap::Add(JNIEnv* env, jobject aJavaObject, nsJavaXPTCStub* aProxy)
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
nsAutoLock lock(gJavaXPCOMLock);
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
Entry* e = NS_STATIC_CAST(Entry*, PL_DHashTableOperate(mHashTable,
@ -606,7 +616,7 @@ JavaToXPTCStubMap::Find(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
if (!aResult)
return NS_ERROR_FAILURE;
nsAutoMonitor mon(gJavaXPCOMMonitor);
nsAutoLock lock(gJavaXPCOMLock);
*aResult = nsnull;
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
@ -637,8 +647,6 @@ JavaToXPTCStubMap::Find(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
nsresult
JavaToXPTCStubMap::Remove(JNIEnv* env, jobject aJavaObject)
{
nsAutoMonitor mon(gJavaXPCOMMonitor);
jint hash = env->CallIntMethod(aJavaObject, hashCodeMID);
PL_DHashTableOperate(mHashTable, NS_INT32_TO_PTR(hash), PL_DHASH_REMOVE);
@ -702,8 +710,6 @@ GetNewOrUsedJavaObject(JNIEnv* env, nsISupports* aXPCOMObject,
return NS_OK;
}
nsAutoMonitor mon(gJavaXPCOMMonitor);
// Get associated Java object from hash table
rv = gNativeToJavaProxyMap->Find(env, aXPCOMObject, aIID, aResult);
if (NS_FAILED(rv))
@ -751,8 +757,6 @@ GetNewOrUsedXPCOMObject(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
}
}
nsAutoMonitor mon(gJavaXPCOMMonitor);
*aIsXPTCStub = PR_TRUE;
nsJavaXPTCStub* stub;

View File

@ -113,7 +113,9 @@ extern JavaToXPTCStubMap* gJavaToXPTCStubMap;
// The Java garbage collector runs in a separate thread. Since it calls the
// finalizeProxy() function in nsJavaWrapper.cpp, we need to make sure that
// all the structures touched by finalizeProxy() are multithread aware.
extern PRMonitor* gJavaXPCOMMonitor;
extern PRLock* gJavaXPCOMLock;
extern PRBool gJavaXPCOMInitialized;
/**
* Initialize global structures used by Javaconnect.

View File

@ -171,7 +171,7 @@ nsJavaXPTCStub::Destroy()
delete (nsJavaXPTCStub*) mChildren[i];
}
if (gJavaXPCOMMonitor) { // if Javaconnect is still initialized
if (gJavaXPCOMInitialized) {
gJavaToXPTCStubMap->Remove(mJavaEnv, mJavaStrongRef);
}
}