From 8167a5c5f44bfa6ac4904bd38a80f90610f77951 Mon Sep 17 00:00:00 2001 From: "bsmedberg%covad.net" Date: Thu, 11 Aug 2005 19:43:01 +0000 Subject: [PATCH] bug 200709 remove dynamic linking of nsTHashtable and family. r=jkeiser sr=alecf --- xpcom/glue/nsBaseHashtable.h | 181 ++++++++++++++++++++++++++- xpcom/glue/nsClassHashtable.h | 11 +- xpcom/glue/nsDataHashtable.h | 21 ---- xpcom/glue/nsInterfaceHashtable.h | 61 +++++++--- xpcom/glue/nsTHashtable.cpp | 24 +--- xpcom/glue/nsTHashtable.h | 196 +++++++++++++++++++++++++++--- 6 files changed, 404 insertions(+), 90 deletions(-) diff --git a/xpcom/glue/nsBaseHashtable.h b/xpcom/glue/nsBaseHashtable.h index d7172f2e71d..9c8038a02db 100644 --- a/xpcom/glue/nsBaseHashtable.h +++ b/xpcom/glue/nsBaseHashtable.h @@ -40,7 +40,8 @@ #include "nsTHashtable.h" #include NEW_H -typedef struct PRRWLock PRRWLock; +#include "prrwlock.h" +#include "nsDebug.h" template class nsBaseHashtable; // forward declaration @@ -183,8 +184,180 @@ protected: void *arg); }; -#ifndef HAVE_CPP_EXTERN_INSTANTIATION - #include "nsBaseHashtableImpl.h" -#endif +// +// nsBaseHashtableET definitions +// + +template +nsBaseHashtableET::nsBaseHashtableET(KeyTypePointer aKey) : + KeyClass(aKey) +{ } + +template +nsBaseHashtableET::nsBaseHashtableET + (const nsBaseHashtableET& toCopy) : + KeyClass(toCopy), + mData(toCopy.mData) +{ } + +template +nsBaseHashtableET::~nsBaseHashtableET() +{ } + +// +// nsBaseHashtable definitions +// + +template +nsBaseHashtable::nsBaseHashtable() +{ } + +template +nsBaseHashtable::~nsBaseHashtable() +{ + if (mLock) + PR_DestroyRWLock(mLock); +} + +template +PRBool +nsBaseHashtable::Init(PRUint32 initSize, + PRBool threadSafe) +{ + if (!nsTHashtable::Init(initSize)) + return PR_FALSE; + + if (!threadSafe) + { + mLock = nsnull; + return PR_TRUE; + } + + mLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "nsBaseHashtable"); + + NS_WARN_IF_FALSE(mLock, "Error creating lock during nsBaseHashtable::Init()"); + + if (!mLock) + return PR_FALSE; + + return PR_TRUE; +} + +template +PRBool +nsBaseHashtable::Get(KeyType aKey, + UserDataType* pData) const +{ + if (mLock) + PR_RWLock_Rlock(mLock); + + EntryType* ent = GetEntry(KeyClass::KeyToPointer(aKey)); + + if (ent) + { + if (pData) + *pData = ent->mData; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; + } + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; +} + +template +PRBool +nsBaseHashtable::Put(KeyType aKey, + UserDataType aData) +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + EntryType* ent = PutEntry(KeyClass::KeyToPointer(aKey)); + + if (!ent) + { + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; + } + + ent->mData = aData; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; +} + +template +void +nsBaseHashtable::Remove(KeyType aKey) +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + RemoveEntry(KeyClass::KeyToPointer(aKey)); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +void +nsBaseHashtable::EnumerateRead + (EnumReadFunction fEnumCall, void* userArg) const +{ + NS_ASSERTION(mTable.entrySize, + "nsBaseHashtable was not initialized properly."); + + if (mLock) + PR_RWLock_Rlock(mLock); + + s_EnumReadArgs enumData = { fEnumCall, userArg }; + PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*,&mTable), + s_EnumStub, + &enumData); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +void nsBaseHashtable::Clear() +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + nsTHashtable::Clear(); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +PLDHashOperator +nsBaseHashtable::s_EnumReadStub + (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg) +{ + EntryType* ent = NS_STATIC_CAST(EntryType*, hdr); + s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg; + + PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg); + + NS_ASSERTION( !(res & PL_DHASH_REMOVE ), + "PL_DHASH_REMOVE return during const enumeration; ignoring."); + + if (res & PL_DHASH_STOP) + return PL_DHASH_STOP; + + return PL_DHASH_NEXT; +} #endif // nsBaseHashtable_h__ diff --git a/xpcom/glue/nsClassHashtable.h b/xpcom/glue/nsClassHashtable.h index 9a0eab2442e..9fa22c3e7d2 100644 --- a/xpcom/glue/nsClassHashtable.h +++ b/xpcom/glue/nsClassHashtable.h @@ -74,14 +74,9 @@ public: PRBool Get(KeyType aKey, UserDataType* pData) const; }; -/* - * this class doesn't have any predefined instances; implementations are - * included here - */ - -#ifndef nsTHashtableImpl_h__ -#include "nsTHashtableImpl.h" -#endif +// +// nsClassHashtable definitions +// template PRBool diff --git a/xpcom/glue/nsDataHashtable.h b/xpcom/glue/nsDataHashtable.h index 7da278d7e26..15c8387f80a 100644 --- a/xpcom/glue/nsDataHashtable.h +++ b/xpcom/glue/nsDataHashtable.h @@ -54,25 +54,4 @@ class nsDataHashtable : public nsBaseHashtable { }; -/** - * declare shared-linkage for common usages of nsDataHashtable. - * - * To avoid including this code in multiple translation units, common usages - * are predeclared with external linkage. To add to this list, include the - * declarations here, definitions in nsTHashtable.cpp and dlldeps.cpp . This - * only works if the configure-test HAVE_CPP_EXTERN_INSTANTIATION succeeds. - */ -#ifndef HAVE_CPP_EXTERN_INSTANTIATION - #include "nsBaseHashtableImpl.h" -#else - #ifndef NO_THASHTABLE_EXTERN_DECL - extern template class NS_COM nsBaseHashtableET; - extern template class NS_COM nsTHashtable< nsBaseHashtableET >; - extern template class NS_COM nsBaseHashtable; - extern template class NS_COM nsDataHashtable; - #else - #include "nsBaseHashtableImpl.h" - #endif -#endif - #endif // nsDataHashtable_h__ diff --git a/xpcom/glue/nsInterfaceHashtable.h b/xpcom/glue/nsInterfaceHashtable.h index 8a5fe61b1c4..78a93d53e73 100644 --- a/xpcom/glue/nsInterfaceHashtable.h +++ b/xpcom/glue/nsInterfaceHashtable.h @@ -75,25 +75,46 @@ public: PRBool Get(KeyType aKey, UserDataType* pData) const; }; -/** - * declare shared-linkage for common usages of nsDataHashtable. - * - * To avoid including this code in multiple translation units, common usages - * are predeclared with external linkage. To add to this list, include the - * declarations here, definitions in nsTHashtable.cpp and dlldeps.cpp . This - * only works if the configure-test HAVE_CPP_EXTERN_INSTANTIATION succeeds. - */ -#ifndef HAVE_CPP_EXTERN_INSTANTIATION - #include "nsInterfaceHashtableImpl.h" -#else - #ifndef NO_THASHTABLE_EXTERN_DECL - extern template class NS_COM nsBaseHashtableET >; - extern template class NS_COM nsTHashtable< nsBaseHashtableET > >; - extern template class NS_COM nsBaseHashtable, nsISupports*>; - extern template class NS_COM nsInterfaceHashtable; - #else - #include "nsInterfaceHashtableImpl.h" - #endif -#endif + +// +// nsInterfaceHashtable definitions +// + +template +PRBool +nsInterfaceHashtable::Get + (KeyType aKey, UserDataType* pInterface) const +{ + if (mLock) + PR_RWLock_Rlock(mLock); + + typename nsBaseHashtable, Interface*>::EntryType* ent = + GetEntry(KeyClass::KeyToPointer(aKey)); + + if (ent) + { + if (pInterface) + { + *pInterface = ent->mData; + + NS_IF_ADDREF(*pInterface); + } + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; + } + + // if the key doesn't exist, set *pInterface to null + // so that it is a valid XPCOM getter + if (pInterface) + *pInterface = nsnull; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; +} #endif // nsInterfaceHashtable_h__ diff --git a/xpcom/glue/nsTHashtable.cpp b/xpcom/glue/nsTHashtable.cpp index b0460f8cb24..37fa998fa2e 100644 --- a/xpcom/glue/nsTHashtable.cpp +++ b/xpcom/glue/nsTHashtable.cpp @@ -35,16 +35,11 @@ * * ***** END LICENSE BLOCK ***** */ -#define NO_THASHTABLE_EXTERN_DECL - #include "nsTHashtable.h" -#include "nsTHashtableImpl.h" -#include "nsInterfaceHashtable.h" -#include "nsInterfaceHashtableImpl.h" -#include "nsDataHashtable.h" #include "nsHashKeys.h" -PLDHashOperator PL_DHashStubEnumRemove(PLDHashTable *table, +PR_IMPLEMENT(PLDHashOperator) +PL_DHashStubEnumRemove(PLDHashTable *table, PLDHashEntryHdr *entry, PRUint32 ordinal, void *userarg) @@ -65,18 +60,3 @@ PRUint32 nsIDHashKey::HashKey(const nsID* id) return h; } - -// explicit instantiation of templates -#ifdef HAVE_CPP_EXTERN_INSTANTIATION - /* instantiate common nsInterfaceHashtable uses */ - template class NS_EXPORT nsBaseHashtableET >; - template class NS_EXPORT nsTHashtable< nsBaseHashtableET > >; - template class NS_EXPORT nsBaseHashtable,nsISupports*>; - template class NS_EXPORT nsInterfaceHashtable; - - /* instantiate common nsDataHashtable uses */ - template class NS_EXPORT nsBaseHashtableET; - template class NS_EXPORT nsTHashtable< nsBaseHashtableET >; - template class NS_EXPORT nsBaseHashtable; - template class NS_EXPORT nsDataHashtable; -#endif // HAVE_CPP_EXTERN_INSTANTIATION diff --git a/xpcom/glue/nsTHashtable.h b/xpcom/glue/nsTHashtable.h index a747c09f58d..bbe1fffb05b 100644 --- a/xpcom/glue/nsTHashtable.h +++ b/xpcom/glue/nsTHashtable.h @@ -40,10 +40,7 @@ #include "nscore.h" #include "pldhash.h" - -#ifdef _MSC_VER -#pragma warning( disable: 4231 ) // 'extern template' nonstandard C++ extension -#endif +#include "nsDebug.h" /** * a base class for templated hashtables. @@ -225,17 +222,186 @@ protected: }; // helper function for Reset() -PLDHashOperator PL_DHashStubEnumRemove(PLDHashTable *table, - PLDHashEntryHdr *entry, - PRUint32 ordinal, - void *userArg); +PR_EXTERN(PLDHashOperator) +PL_DHashStubEnumRemove(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 ordinal, + void *userArg); -/** - * if we can't declare external linkage for templates, we need to include the - * implementation header. - */ -#ifndef HAVE_CPP_EXTERN_INSTANTIATION -#include "nsTHashtableImpl.h" -#endif + +// +// template definitions +// + +template +nsTHashtable::nsTHashtable() +{ + // entrySize is our "I'm initialized" indicator + mTable.entrySize = 0; +} + +template +nsTHashtable::~nsTHashtable() +{ + if (mTable.entrySize) + PL_DHashTableFinish(&mTable); +} + +template +PRBool +nsTHashtable::Init(PRUint32 initSize) +{ + if (mTable.entrySize) + { + NS_ERROR("nsTHashtable::Init() should not be called twice."); + return PR_FALSE; + } + + if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize)) + { + // if failed, reset "flag" + mTable.entrySize = 0; + return PR_FALSE; + } + + return PR_TRUE; +} + +template +EntryType* +nsTHashtable::GetEntry(KeyTypePointer aKey) const +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + return NS_REINTERPRET_CAST(EntryType*, + PL_DHashTableOperate( + NS_CONST_CAST(PLDHashTable*,&mTable), + aKey, + PL_DHASH_LOOKUP)); +} + +template +EntryType* +nsTHashtable::PutEntry(KeyTypePointer aKey) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + return (EntryType*) PL_DHashTableOperate(&mTable, aKey, PL_DHASH_ADD); +} + +template +void +nsTHashtable::RemoveEntry(KeyTypePointer aKey) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + PL_DHashTableOperate(&mTable, aKey, PL_DHASH_REMOVE); + + return; +} + +template +PRUint32 +nsTHashtable::EnumerateEntries(Enumerator enumFunc, void* userArg) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + s_EnumArgs args = { enumFunc, userArg }; + + return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args); +} + +template +void +nsTHashtable::Clear() +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull); +} + +// static definitions + +template +PLDHashTableOps +nsTHashtable::sOps = +{ + ::PL_DHashAllocTable, + ::PL_DHashFreeTable, + s_GetKey, + s_HashKey, + s_MatchEntry, + EntryType::AllowMemMove() ? ::PL_DHashMoveEntryStub : s_CopyEntry, + s_ClearEntry, + ::PL_DHashFinalizeStub, + s_InitEntry +}; + +template +const void* +nsTHashtable::s_GetKey(PLDHashTable *table, + PLDHashEntryHdr *entry) +{ + return ((EntryType*) entry)->GetKeyPointer(); +} + +template +PLDHashNumber +nsTHashtable::s_HashKey(PLDHashTable *table, + const void *key) +{ + return EntryType::HashKey(NS_REINTERPRET_CAST(const KeyTypePointer, key)); +} + +template +PRBool +nsTHashtable::s_MatchEntry(PLDHashTable *table, + const PLDHashEntryHdr *entry, + const void *key) +{ + return ((const EntryType*) entry)->KeyEquals( + NS_REINTERPRET_CAST(const KeyTypePointer, key)); +} + +template +void +nsTHashtable::s_CopyEntry(PLDHashTable *table, + const PLDHashEntryHdr *from, + PLDHashEntryHdr *to) +{ + new(to) EntryType(* NS_REINTERPRET_CAST(const EntryType*,from)); + + NS_CONST_CAST(EntryType*,NS_REINTERPRET_CAST(const EntryType*,from))->~EntryType(); +} + +template +void +nsTHashtable::s_ClearEntry(PLDHashTable *table, + PLDHashEntryHdr *entry) +{ + NS_REINTERPRET_CAST(EntryType*,entry)->~EntryType(); +} + +template +void +nsTHashtable::s_InitEntry(PLDHashTable *table, + PLDHashEntryHdr *entry, + const void *key) +{ + new(entry) EntryType(NS_REINTERPRET_CAST(KeyTypePointer,key)); +} + +template +PLDHashOperator +nsTHashtable::s_EnumStub(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 number, + void *arg) +{ + // dereferences the function-pointer to the user's enumeration function + return (* NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userFunc)( + NS_REINTERPRET_CAST(EntryType*,entry), + NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userArg); +} #endif // nsTHashtable_h__