mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 193031 fix category manager to use aPersist parameter. Bug 54639 Category Manager is not thread-safe. Bug 208437 separate threadsafe nsBaseHashtable into super-class nsBaseHashtableMT. r=dougt/alecf I know Sun Workshop builds are still broken... working on it.
This commit is contained in:
parent
0c2a7ccbbd
commit
eaf415b72d
@ -39,7 +39,7 @@
|
||||
#define nsBaseHashtable_h__
|
||||
|
||||
#include "nsTHashtable.h"
|
||||
#include "prrwlock.h"
|
||||
#include "prlock.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
@ -86,27 +86,18 @@ public:
|
||||
typedef typename KeyClass::KeyType KeyType;
|
||||
typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
|
||||
|
||||
/**
|
||||
* The constructor does not initialize, you must call Init() after
|
||||
* construction.
|
||||
*/
|
||||
nsBaseHashtable();
|
||||
|
||||
/**
|
||||
* destructor finalizes and deallocates hashtable
|
||||
*/
|
||||
~nsBaseHashtable();
|
||||
// default constructor+destructor are fine
|
||||
|
||||
/**
|
||||
* Initialize the object.
|
||||
* @param initSize the initial number of buckets in the hashtable,
|
||||
default 16
|
||||
* default 16
|
||||
* @param threadSafe whether to provide read/write
|
||||
* locking on all class methods
|
||||
* @return PR_TRUE if the object was initialized properly.
|
||||
*/
|
||||
PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE,
|
||||
PRBool threadSafe = PR_FALSE);
|
||||
PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
|
||||
{ return nsTHashtable<EntryType>::Init(initSize); }
|
||||
|
||||
/**
|
||||
* Check whether the table has been initialized.
|
||||
@ -115,6 +106,13 @@ public:
|
||||
*/
|
||||
PRBool IsInitialized() const { return mTable.entrySize; }
|
||||
|
||||
/**
|
||||
* Return the number of entries in the table.
|
||||
* @return number of entries
|
||||
*/
|
||||
PRUint32 Count() const
|
||||
{ return nsTHashtable<EntryType>::Count(); }
|
||||
|
||||
/**
|
||||
* retrieve the value for a key.
|
||||
* @param aKey the key to retreive
|
||||
@ -124,7 +122,18 @@ public:
|
||||
* @return PR_TRUE if the key exists. If key does not exist, pData is not
|
||||
* modified.
|
||||
*/
|
||||
PRBool Get(KeyType aKey, UserDataType* pData) const;
|
||||
PRBool Get(KeyType aKey, UserDataType* pData) const
|
||||
{
|
||||
EntryType* ent = GetEntry(aKey);
|
||||
|
||||
if (!ent)
|
||||
return PR_FALSE;
|
||||
|
||||
if (pData)
|
||||
*pData = ent->mData;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* put a new value for the associated key
|
||||
@ -132,13 +141,23 @@ public:
|
||||
* @param aData the new data
|
||||
* @return always PR_TRUE, unless memory allocation failed
|
||||
*/
|
||||
PRBool Put(KeyType aKey, UserDataType aData);
|
||||
PRBool Put(KeyType aKey, UserDataType aData)
|
||||
{
|
||||
EntryType* ent = PutEntry(aKey);
|
||||
|
||||
if (!ent)
|
||||
return PR_FALSE;
|
||||
|
||||
ent->mData = aData;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the data for the associated key
|
||||
* @param aKey the key to remove from the hashtable
|
||||
*/
|
||||
void Remove(KeyType aKey);
|
||||
void Remove(KeyType aKey) { RemoveEntry(aKey); }
|
||||
|
||||
/**
|
||||
* function type provided by the application for enumeration.
|
||||
@ -161,7 +180,16 @@ public:
|
||||
* @param enumFunc enumeration callback
|
||||
* @param userArg passed unchanged to the EnumReadFunction
|
||||
*/
|
||||
PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
|
||||
PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
|
||||
{
|
||||
NS_ASSERTION(mTable.entrySize,
|
||||
"nsBaseHashtable was not initialized properly.");
|
||||
|
||||
s_EnumReadArgs enumData = { enumFunc, userArg };
|
||||
return PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*, &mTable),
|
||||
s_EnumReadStub,
|
||||
&enumData);
|
||||
}
|
||||
|
||||
/**
|
||||
* function type provided by the application for enumeration.
|
||||
@ -185,16 +213,23 @@ public:
|
||||
* @param enumFunc enumeration callback
|
||||
* @param userArg passed unchanged to the EnumFunction
|
||||
*/
|
||||
PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
|
||||
PRUint32 Enumerate(EnumFunction enumFunc, void* userArg)
|
||||
{
|
||||
NS_ASSERTION(mTable.entrySize,
|
||||
"nsBaseHashtable was not initialized properly.");
|
||||
|
||||
s_EnumArgs enumData = { enumFunc, userArg };
|
||||
return PL_DHashTableEnumerate(&mTable,
|
||||
s_EnumStub,
|
||||
&enumData);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the hashtable, removing all entries
|
||||
*/
|
||||
void Clear();
|
||||
void Clear() { nsTHashtable<EntryType>::Clear(); }
|
||||
|
||||
protected:
|
||||
PRRWLock* mLock;
|
||||
|
||||
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
using nsTHashtable<nsBaseHashtableET<KeyClass,DataType> >::mTable;
|
||||
#endif
|
||||
@ -227,6 +262,46 @@ protected:
|
||||
void *arg);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is a thread-safe version of nsBaseHashtable.
|
||||
*/
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
class nsBaseHashtableMT :
|
||||
protected nsBaseHashtable<KeyClass,DataType,UserDataType>
|
||||
{
|
||||
public:
|
||||
typedef typename
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
|
||||
typedef typename
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
|
||||
typedef typename
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
|
||||
typedef typename
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
|
||||
|
||||
nsBaseHashtableMT() : mLock(nsnull) { }
|
||||
~nsBaseHashtableMT();
|
||||
|
||||
PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
|
||||
PRBool IsInitialized() const { return (PRBool) mLock; }
|
||||
PRUint32 Count() const;
|
||||
PRBool Get(KeyType aKey, UserDataType* pData) const;
|
||||
PRBool Put(KeyType aKey, UserDataType aData);
|
||||
void Remove(KeyType aKey);
|
||||
|
||||
PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
|
||||
PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
|
||||
void Clear();
|
||||
|
||||
protected:
|
||||
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
using nsTHashtable<EntryType>::mTable;
|
||||
#endif
|
||||
|
||||
PRLock* mLock;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// nsBaseHashtableET definitions
|
||||
//
|
||||
@ -247,170 +322,11 @@ template<class KeyClass,class DataType>
|
||||
nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
|
||||
{ }
|
||||
|
||||
|
||||
//
|
||||
// nsBaseHashtable definitions
|
||||
//
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::nsBaseHashtable()
|
||||
: mLock(nsnull)
|
||||
{ }
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::~nsBaseHashtable()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyRWLock(mLock);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize,
|
||||
PRBool threadSafe)
|
||||
{
|
||||
if (!nsTHashtable<EntryType>::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<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(KeyType aKey,
|
||||
UserDataType* pData) const
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Rlock(mLock);
|
||||
|
||||
EntryType* ent = GetEntry(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<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(KeyType aKey,
|
||||
UserDataType aData)
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Wlock(mLock);
|
||||
|
||||
EntryType* ent = PutEntry(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<class KeyClass,class DataType,class UserDataType>
|
||||
void
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Wlock(mLock);
|
||||
|
||||
RemoveEntry(aKey);
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRUint32
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::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 };
|
||||
PRUint32 count =
|
||||
PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*,&mTable),
|
||||
s_EnumReadStub,
|
||||
&enumData);
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRUint32
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate
|
||||
(EnumFunction fEnumCall, void* userArg)
|
||||
{
|
||||
NS_ASSERTION(mTable.entrySize,
|
||||
"nsBaseHashtable was not initialized properly.");
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Wlock(mLock);
|
||||
|
||||
s_EnumArgs enumData = { fEnumCall, userArg };
|
||||
PRUint32 count =
|
||||
PL_DHashTableEnumerate(&mTable,
|
||||
s_EnumStub,
|
||||
&enumData);
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
void nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear()
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Wlock(mLock);
|
||||
|
||||
nsTHashtable<EntryType>::Clear();
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PLDHashOperator
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
|
||||
@ -441,4 +357,110 @@ nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
|
||||
return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsBaseHashtableMT definitions
|
||||
//
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
|
||||
{
|
||||
if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
|
||||
return PR_FALSE;
|
||||
|
||||
mLock = PR_NewLock();
|
||||
NS_WARN_IF_FALSE(mLock, "Error creating lock during nsBaseHashtableL::Init()");
|
||||
|
||||
return (mLock != nsnull);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRUint32
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
PRUint32 count = nsTHashtable<EntryType>::Count();
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType aKey,
|
||||
UserDataType* pData) const
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
PRBool res =
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRBool
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType aKey,
|
||||
UserDataType aData)
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
PRBool res =
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
void
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
|
||||
PR_Unlock(mLock);
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRUint32
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
|
||||
(EnumReadFunction fEnumCall, void* userArg) const
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
PRUint32 count =
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
PRUint32
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
|
||||
(EnumFunction fEnumCall, void* userArg)
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
PRUint32 count =
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class KeyClass,class DataType,class UserDataType>
|
||||
void
|
||||
nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
|
||||
PR_Unlock(mLock);
|
||||
}
|
||||
|
||||
#endif // nsBaseHashtable_h__
|
||||
|
@ -59,14 +59,27 @@ public:
|
||||
typedef T* UserDataType;
|
||||
|
||||
/**
|
||||
* @copydoc nsBaseHashtable::nsBaseHashtable
|
||||
* @copydoc nsBaseHashtable::Get
|
||||
* @param pData if the key doesn't exist, pData will be set to nsnull.
|
||||
*/
|
||||
nsClassHashtable() { }
|
||||
PRBool Get(KeyType aKey, UserDataType* pData) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* destructor, cleans up properly
|
||||
*/
|
||||
~nsClassHashtable() { }
|
||||
|
||||
/**
|
||||
* Thread-safe version of nsClassHashtable
|
||||
* @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
|
||||
* for a complete specification.
|
||||
* @param Class the class-type being wrapped
|
||||
* @see nsInterfaceHashtable, nsClassHashtable
|
||||
*/
|
||||
template<class KeyClass,class T>
|
||||
class nsClassHashtableMT :
|
||||
public nsBaseHashtableMT< KeyClass, nsAutoPtr<T>, T* >
|
||||
{
|
||||
public:
|
||||
typedef typename KeyClass::KeyType KeyType;
|
||||
typedef T* UserDataType;
|
||||
|
||||
/**
|
||||
* @copydoc nsBaseHashtable::Get
|
||||
@ -76,7 +89,7 @@ public:
|
||||
|
||||
protected:
|
||||
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
using nsBaseHashtable<KeyClass, nsAutoPtr<T>, T*>::mLock;
|
||||
using nsBaseHashtableMT<KeyClass, nsAutoPtr<T>, T*>::mLock;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -89,9 +102,6 @@ template<class KeyClass,class T>
|
||||
PRBool
|
||||
nsClassHashtable<KeyClass,T>::Get(KeyType aKey, T** retVal) const
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Rlock(mLock);
|
||||
|
||||
typename nsBaseHashtable<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
|
||||
GetEntry(aKey);
|
||||
|
||||
@ -100,16 +110,43 @@ nsClassHashtable<KeyClass,T>::Get(KeyType aKey, T** retVal) const
|
||||
if (retVal)
|
||||
*retVal = ent->mData;
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (retVal)
|
||||
*retVal = nsnull;
|
||||
|
||||
return PR_FALSE;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// nsClassHashtableMT definitions
|
||||
//
|
||||
|
||||
template<class KeyClass,class T>
|
||||
PRBool
|
||||
nsClassHashtableMT<KeyClass,T>::Get(KeyType aKey, T** retVal) const
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
|
||||
typename nsBaseHashtableMT<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
|
||||
GetEntry(aKey);
|
||||
|
||||
if (ent)
|
||||
{
|
||||
if (retVal)
|
||||
*retVal = ent->mData;
|
||||
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
*retVal = nsnull;
|
||||
if (retVal)
|
||||
*retVal = nsnull;
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return PR_FALSE;
|
||||
};
|
||||
|
@ -54,4 +54,9 @@ class nsDataHashtable :
|
||||
public nsBaseHashtable<KeyClass,DataType,DataType>
|
||||
{ };
|
||||
|
||||
template<class KeyClass,class DataType>
|
||||
class nsDataHashtableMT :
|
||||
public nsBaseHashtableMT<KeyClass,DataType,DataType>
|
||||
{ };
|
||||
|
||||
#endif // nsDataHashtable_h__
|
||||
|
@ -58,6 +58,7 @@
|
||||
* nsUint32HashKey
|
||||
* nsISupportsHashKey
|
||||
* nsIDHashKey
|
||||
* nsDepCharHashKey
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -211,4 +212,40 @@ private:
|
||||
const nsID mID;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* hashkey wrapper for "dependent" const char*; this class does not "own"
|
||||
* its string pointer.
|
||||
*
|
||||
* This class must only be used if the strings have a lifetime longer than
|
||||
* the hashtable they occupy. This normally occurs only for static
|
||||
* strings or strings that have been arena-allocated.
|
||||
*
|
||||
* @see nsTHashtable::EntryType for specification
|
||||
*/
|
||||
class NS_COM nsDepCharHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const char* KeyType;
|
||||
typedef const char* KeyTypePointer;
|
||||
|
||||
nsDepCharHashKey(const char* aKey) { mKey = aKey; }
|
||||
nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
|
||||
~nsDepCharHashKey() { }
|
||||
|
||||
const char* GetKey() const { return mKey; }
|
||||
const char* GetKeyPointer() const { return mKey; }
|
||||
PRBool KeyEquals(const char* aKey) const
|
||||
{
|
||||
return !strcmp(mKey, aKey);
|
||||
}
|
||||
|
||||
static const char* KeyToPointer(const char* aKey) { return aKey; }
|
||||
static PLDHashNumber HashKey(const char* aKey) { return nsCRT::HashCode(aKey); }
|
||||
enum { ALLOW_MEMMOVE = PR_TRUE };
|
||||
|
||||
private:
|
||||
const char* mKey;
|
||||
};
|
||||
|
||||
#endif // nsTHashKeys_h__
|
||||
|
@ -57,15 +57,28 @@ class nsInterfaceHashtable :
|
||||
public:
|
||||
typedef typename KeyClass::KeyType KeyType;
|
||||
typedef Interface* UserDataType;
|
||||
/**
|
||||
* @copydoc nsBaseHashtable::nsBaseHashtable
|
||||
*/
|
||||
nsInterfaceHashtable() { }
|
||||
|
||||
/**
|
||||
* destructor, cleans up properly
|
||||
* @copydoc nsBaseHashtable::Get
|
||||
* @param pData This is an XPCOM getter, so pData is already_addrefed.
|
||||
* If the key doesn't exist, pData will be set to nsnull.
|
||||
*/
|
||||
~nsInterfaceHashtable() { }
|
||||
PRBool Get(KeyType aKey, UserDataType* pData) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Thread-safe version of nsInterfaceHashtable
|
||||
* @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
|
||||
* for a complete specification.
|
||||
* @param Interface the interface-type being wrapped
|
||||
*/
|
||||
template<class KeyClass,class Interface>
|
||||
class nsInterfaceHashtableMT :
|
||||
public nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
|
||||
{
|
||||
public:
|
||||
typedef typename KeyClass::KeyType KeyType;
|
||||
typedef Interface* UserDataType;
|
||||
|
||||
/**
|
||||
* @copydoc nsBaseHashtable::Get
|
||||
@ -76,7 +89,7 @@ public:
|
||||
|
||||
protected:
|
||||
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
|
||||
using nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::mLock;
|
||||
using nsBaseHashtableMT<KeyClass, nsCOMPtr<Interface>, Interface*>::mLock;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -90,9 +103,6 @@ PRBool
|
||||
nsInterfaceHashtable<KeyClass,Interface>::Get
|
||||
(KeyType aKey, UserDataType* pInterface) const
|
||||
{
|
||||
if (mLock)
|
||||
PR_RWLock_Rlock(mLock);
|
||||
|
||||
typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
|
||||
GetEntry(aKey);
|
||||
|
||||
@ -105,8 +115,42 @@ nsInterfaceHashtable<KeyClass,Interface>::Get
|
||||
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;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsInterfaceHashtableMT definitions
|
||||
//
|
||||
|
||||
template<class KeyClass,class Interface>
|
||||
PRBool
|
||||
nsInterfaceHashtableMT<KeyClass,Interface>::Get
|
||||
(KeyType aKey, UserDataType* pInterface) const
|
||||
{
|
||||
PR_Lock(mLock);
|
||||
|
||||
typename nsBaseHashtableMT<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
|
||||
GetEntry(aKey);
|
||||
|
||||
if (ent)
|
||||
{
|
||||
if (pInterface)
|
||||
{
|
||||
*pInterface = ent->mData;
|
||||
|
||||
NS_IF_ADDREF(*pInterface);
|
||||
}
|
||||
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -116,8 +160,7 @@ nsInterfaceHashtable<KeyClass,Interface>::Get
|
||||
if (pInterface)
|
||||
*pInterface = nsnull;
|
||||
|
||||
if (mLock)
|
||||
PR_RWLock_Unlock(mLock);
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -143,6 +143,12 @@ public:
|
||||
*/
|
||||
typedef typename EntryType::KeyTypePointer KeyTypePointer;
|
||||
|
||||
/**
|
||||
* Return the number of entries in the table.
|
||||
* @return number of entries
|
||||
*/
|
||||
PRUint32 Count() const { return mTable.entryCount; }
|
||||
|
||||
/**
|
||||
* Get the entry associated with a key.
|
||||
* @param aKey the key to retrieve
|
||||
@ -283,6 +289,12 @@ protected:
|
||||
PLDHashEntryHdr *entry,
|
||||
PRUint32 number,
|
||||
void *arg);
|
||||
private:
|
||||
// copy constructor, not implemented
|
||||
nsTHashtable(nsTHashtable<EntryType>& toCopy);
|
||||
|
||||
// assignment operator, not implemented
|
||||
nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
|
||||
};
|
||||
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user