From f91b8f9f950fb254bd138d5fdd5111675cf7a468 Mon Sep 17 00:00:00 2001 From: "dp%netscape.com" Date: Tue, 30 Mar 1999 08:15:39 +0000 Subject: [PATCH] Thread Safe nsHashtable (on demand only) git-svn-id: svn://10.0.0.236/trunk@25609 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xpcom/components/nsComponentManager.cpp | 6 +-- mozilla/xpcom/ds/nsHashtable.cpp | 47 +++++++++++++++++-- mozilla/xpcom/ds/nsHashtable.h | 4 +- mozilla/xpcom/public/nsHashtable.h | 4 +- mozilla/xpcom/src/nsComponentManager.cpp | 6 +-- mozilla/xpcom/src/nsHashtable.cpp | 47 +++++++++++++++++-- 6 files changed, 98 insertions(+), 16 deletions(-) diff --git a/mozilla/xpcom/components/nsComponentManager.cpp b/mozilla/xpcom/components/nsComponentManager.cpp index b19a7793f5a..7e1d58e2066 100644 --- a/mozilla/xpcom/components/nsComponentManager.cpp +++ b/mozilla/xpcom/components/nsComponentManager.cpp @@ -149,12 +149,12 @@ nsComponentManagerImpl::nsComponentManagerImpl() nsresult nsComponentManagerImpl::Init(void) { if (mFactories == NULL) { - mFactories = new nsHashtable(); + mFactories = new nsHashtable(256, PR_TRUE); if (mFactories == NULL) return NS_ERROR_OUT_OF_MEMORY; } if (mProgIDs == NULL) { - mProgIDs = new nsHashtable(); + mProgIDs = new nsHashtable(256, PR_TRUE); if (mProgIDs == NULL) return NS_ERROR_OUT_OF_MEMORY; } @@ -164,7 +164,7 @@ nsresult nsComponentManagerImpl::Init(void) return NS_ERROR_OUT_OF_MEMORY; } if (mDllStore == NULL) { - mDllStore = new nsHashtable(); + mDllStore = new nsHashtable(256, PR_TRUE); if (mDllStore == NULL) return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/xpcom/ds/nsHashtable.cpp b/mozilla/xpcom/ds/nsHashtable.cpp index d1ab44efa0e..30f665abe91 100644 --- a/mozilla/xpcom/ds/nsHashtable.cpp +++ b/mozilla/xpcom/ds/nsHashtable.cpp @@ -17,6 +17,7 @@ */ #include "prmem.h" +#include "prlog.h" #include "nsHashtable.h" // @@ -95,24 +96,42 @@ nsHashKey::~nsHashKey(void) { } -nsHashtable::nsHashtable(PRUint32 aInitSize) { +nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe) + : mLock(NULL) +{ hashtable = PL_NewHashTable(aInitSize, _hashValue, _hashKeyCompare, _hashValueCompare, &_hashAllocOps, NULL); + if (threadSafe == PR_TRUE) + { + mLock = PR_NewLock(); + if (mLock == NULL) + { + // Cannot create a lock. If running on a multiprocessing system + // we are sure to die. + PR_ASSERT(mLock != NULL); + } + } } nsHashtable::~nsHashtable() { PL_HashTableDestroy(hashtable); + if (mLock) PR_DestroyLock(mLock); } PRBool nsHashtable::Exists(nsHashKey *aKey) { PLHashNumber hash = aKey->HashValue(); + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); + if (mLock) PR_Unlock(mLock); + return *hep != NULL; } @@ -120,6 +139,9 @@ void *nsHashtable::Put(nsHashKey *aKey, void *aData) { void *res = NULL; PLHashNumber hash = aKey->HashValue(); PLHashEntry *he; + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); if ((he = *hep) != NULL) { @@ -130,16 +152,28 @@ void *nsHashtable::Put(nsHashKey *aKey, void *aData) { (void *) aKey->Clone(), aData); } + if (mLock) PR_Unlock(mLock); + return res; } void *nsHashtable::Get(nsHashKey *aKey) { - return PL_HashTableLookup(hashtable, (void *) aKey); + + if (mLock) PR_Lock(mLock); + + void *ret = PL_HashTableLookup(hashtable, (void *) aKey); + + if (mLock) PR_Unlock(mLock); + + return ret; } void *nsHashtable::Remove(nsHashKey *aKey) { PLHashNumber hash = aKey->HashValue(); PLHashEntry *he; + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); void *res = NULL; @@ -148,6 +182,8 @@ void *nsHashtable::Remove(nsHashKey *aKey) { PL_HashTableRawRemove(hashtable, hep, he); } + if (mLock) PR_Unlock(mLock); + return res; } @@ -159,8 +195,11 @@ static PR_CALLBACK PRIntn _hashEnumerateCopy(PLHashEntry *he, PRIntn i, void *ar } nsHashtable * nsHashtable::Clone() { - nsHashtable *newHashTable = new nsHashtable(hashtable->nentries); - + PRBool threadSafe = PR_FALSE; + if (mLock) + threadSafe = PR_TRUE; + nsHashtable *newHashTable = new nsHashtable(hashtable->nentries, threadSafe); + PL_HashTableEnumerateEntries(hashtable, _hashEnumerateCopy, newHashTable); return newHashTable; } diff --git a/mozilla/xpcom/ds/nsHashtable.h b/mozilla/xpcom/ds/nsHashtable.h index 345f4548a08..f5d2473e67f 100644 --- a/mozilla/xpcom/ds/nsHashtable.h +++ b/mozilla/xpcom/ds/nsHashtable.h @@ -20,6 +20,7 @@ #define nsHashtable_h__ #include "plhash.h" +#include "prlock.h" #include "nsCom.h" class NS_COM nsHashKey { @@ -40,9 +41,10 @@ class NS_COM nsHashtable { private: // members PLHashTable *hashtable; + PRLock *mLock; public: - nsHashtable(PRUint32 aSize = 256); + nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE); ~nsHashtable(); PRInt32 Count(void) { return hashtable->nentries; } diff --git a/mozilla/xpcom/public/nsHashtable.h b/mozilla/xpcom/public/nsHashtable.h index 345f4548a08..f5d2473e67f 100644 --- a/mozilla/xpcom/public/nsHashtable.h +++ b/mozilla/xpcom/public/nsHashtable.h @@ -20,6 +20,7 @@ #define nsHashtable_h__ #include "plhash.h" +#include "prlock.h" #include "nsCom.h" class NS_COM nsHashKey { @@ -40,9 +41,10 @@ class NS_COM nsHashtable { private: // members PLHashTable *hashtable; + PRLock *mLock; public: - nsHashtable(PRUint32 aSize = 256); + nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE); ~nsHashtable(); PRInt32 Count(void) { return hashtable->nentries; } diff --git a/mozilla/xpcom/src/nsComponentManager.cpp b/mozilla/xpcom/src/nsComponentManager.cpp index b19a7793f5a..7e1d58e2066 100644 --- a/mozilla/xpcom/src/nsComponentManager.cpp +++ b/mozilla/xpcom/src/nsComponentManager.cpp @@ -149,12 +149,12 @@ nsComponentManagerImpl::nsComponentManagerImpl() nsresult nsComponentManagerImpl::Init(void) { if (mFactories == NULL) { - mFactories = new nsHashtable(); + mFactories = new nsHashtable(256, PR_TRUE); if (mFactories == NULL) return NS_ERROR_OUT_OF_MEMORY; } if (mProgIDs == NULL) { - mProgIDs = new nsHashtable(); + mProgIDs = new nsHashtable(256, PR_TRUE); if (mProgIDs == NULL) return NS_ERROR_OUT_OF_MEMORY; } @@ -164,7 +164,7 @@ nsresult nsComponentManagerImpl::Init(void) return NS_ERROR_OUT_OF_MEMORY; } if (mDllStore == NULL) { - mDllStore = new nsHashtable(); + mDllStore = new nsHashtable(256, PR_TRUE); if (mDllStore == NULL) return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/xpcom/src/nsHashtable.cpp b/mozilla/xpcom/src/nsHashtable.cpp index d1ab44efa0e..30f665abe91 100644 --- a/mozilla/xpcom/src/nsHashtable.cpp +++ b/mozilla/xpcom/src/nsHashtable.cpp @@ -17,6 +17,7 @@ */ #include "prmem.h" +#include "prlog.h" #include "nsHashtable.h" // @@ -95,24 +96,42 @@ nsHashKey::~nsHashKey(void) { } -nsHashtable::nsHashtable(PRUint32 aInitSize) { +nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe) + : mLock(NULL) +{ hashtable = PL_NewHashTable(aInitSize, _hashValue, _hashKeyCompare, _hashValueCompare, &_hashAllocOps, NULL); + if (threadSafe == PR_TRUE) + { + mLock = PR_NewLock(); + if (mLock == NULL) + { + // Cannot create a lock. If running on a multiprocessing system + // we are sure to die. + PR_ASSERT(mLock != NULL); + } + } } nsHashtable::~nsHashtable() { PL_HashTableDestroy(hashtable); + if (mLock) PR_DestroyLock(mLock); } PRBool nsHashtable::Exists(nsHashKey *aKey) { PLHashNumber hash = aKey->HashValue(); + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); + if (mLock) PR_Unlock(mLock); + return *hep != NULL; } @@ -120,6 +139,9 @@ void *nsHashtable::Put(nsHashKey *aKey, void *aData) { void *res = NULL; PLHashNumber hash = aKey->HashValue(); PLHashEntry *he; + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); if ((he = *hep) != NULL) { @@ -130,16 +152,28 @@ void *nsHashtable::Put(nsHashKey *aKey, void *aData) { (void *) aKey->Clone(), aData); } + if (mLock) PR_Unlock(mLock); + return res; } void *nsHashtable::Get(nsHashKey *aKey) { - return PL_HashTableLookup(hashtable, (void *) aKey); + + if (mLock) PR_Lock(mLock); + + void *ret = PL_HashTableLookup(hashtable, (void *) aKey); + + if (mLock) PR_Unlock(mLock); + + return ret; } void *nsHashtable::Remove(nsHashKey *aKey) { PLHashNumber hash = aKey->HashValue(); PLHashEntry *he; + + if (mLock) PR_Lock(mLock); + PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey); void *res = NULL; @@ -148,6 +182,8 @@ void *nsHashtable::Remove(nsHashKey *aKey) { PL_HashTableRawRemove(hashtable, hep, he); } + if (mLock) PR_Unlock(mLock); + return res; } @@ -159,8 +195,11 @@ static PR_CALLBACK PRIntn _hashEnumerateCopy(PLHashEntry *he, PRIntn i, void *ar } nsHashtable * nsHashtable::Clone() { - nsHashtable *newHashTable = new nsHashtable(hashtable->nentries); - + PRBool threadSafe = PR_FALSE; + if (mLock) + threadSafe = PR_TRUE; + nsHashtable *newHashTable = new nsHashtable(hashtable->nentries, threadSafe); + PL_HashTableEnumerateEntries(hashtable, _hashEnumerateCopy, newHashTable); return newHashTable; }