Fixed nsSupportsHashtable behaviour and API to fix leaks in

nsDirectoryService. Fixes bugs #38606 and #39859.

a=waterson; r=rayw,brendan,warren
This commit is contained in:
inaky.gonzalez%intel.com 2000-06-06 22:06:56 +00:00
Родитель 63d4464beb
Коммит 98157fd5a1
20 изменённых файлов: 154 добавлений и 128 удалений

Просмотреть файл

@ -855,7 +855,7 @@ NS_IMETHODIMP nsChromeRegistry::LoadDataSource(const nsCString &aFileName,
nsCOMPtr<nsISupports> supports = do_QueryInterface(remote); nsCOMPtr<nsISupports> supports = do_QueryInterface(remote);
nsStringKey skey(key); nsStringKey skey(key);
mDataSourceTable->Put(&skey, (void*)supports.get()); mDataSourceTable->Put(&skey, supports.get());
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -2444,8 +2444,7 @@ nsEventStateManager::RegisterAccessKey(nsIFrame * aFrame, nsIContent* aContent,
if (content) { if (content) {
nsVoidKey key((void*)aKey); nsVoidKey key((void*)aKey);
nsIContent* oldContent = NS_STATIC_CAST(nsIContent*, mAccessKeys->Put(&key, content)); mAccessKeys->Put(&key, content);
NS_IF_RELEASE(oldContent);
} }
return NS_OK; return NS_OK;

Просмотреть файл

@ -126,8 +126,7 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
nsISupportsKey key(aContent); nsISupportsKey key(aContent);
if (aBinding) { if (aBinding) {
nsIXBLBinding* oldBinding = NS_STATIC_CAST(nsIXBLBinding*, mBindingTable->Put(&key, aBinding)); mBindingTable->Put (&key, aBinding);
NS_IF_RELEASE(oldBinding);
} }
else else
mBindingTable->Remove(&key); mBindingTable->Remove(&key);

Просмотреть файл

@ -52,16 +52,14 @@ nsControllerCommandManager::RegisterCommand(const PRUnichar *commandName, nsICon
{ {
nsStringKey commandKey(commandName); nsStringKey commandKey(commandName);
void* replacedCmd = mCommandsTable.Put(&commandKey, (void*)aCommand); if (mCommandsTable.Put (&commandKey, aCommand))
#if DEBUG
if (replacedCmd)
{ {
#if DEBUG
nsCAutoString msg("Replacing existing command -- "); nsCAutoString msg("Replacing existing command -- ");
msg.AppendWithConversion(commandName); msg.AppendWithConversion(commandName);
NS_WARNING(msg); NS_WARNING(msg);
}
#endif #endif
}
return NS_OK; return NS_OK;
} }
@ -71,8 +69,8 @@ nsControllerCommandManager::UnregisterCommand(const PRUnichar *commandName, nsIC
{ {
nsStringKey commandKey(commandName); nsStringKey commandKey(commandName);
void* foundCommand = mCommandsTable.Remove(&commandKey); PRBool any_object_actually_removed_p = mCommandsTable.Remove (&commandKey);
return (foundCommand) ? NS_OK : NS_ERROR_FAILURE; return any_object_actually_removed_p? NS_OK : NS_ERROR_FAILURE;
} }
@ -84,7 +82,7 @@ nsControllerCommandManager::FindCommandHandler(const PRUnichar *aCommandName, ns
*outCommand = NULL; *outCommand = NULL;
nsStringKey commandKey(aCommandName); nsStringKey commandKey(aCommandName);
void* foundCommand = mCommandsTable.Get(&commandKey); // this does the addref nsISupports* foundCommand = mCommandsTable.Get(&commandKey); // this does the addref
if (!foundCommand) return NS_ERROR_FAILURE; if (!foundCommand) return NS_ERROR_FAILURE;
*outCommand = NS_REINTERPRET_CAST(nsIControllerCommand*, foundCommand); *outCommand = NS_REINTERPRET_CAST(nsIControllerCommand*, foundCommand);

Просмотреть файл

@ -159,8 +159,9 @@ nsXULPrototypeCache::PutPrototype(nsIXULPrototypeDocument* aDocument)
rv = aDocument->GetURI(getter_AddRefs(uri)); rv = aDocument->GetURI(getter_AddRefs(uri));
nsIURIKey key(uri); nsIURIKey key(uri);
nsIXULPrototypeDocument* oldproto = NS_STATIC_CAST(nsIXULPrototypeDocument*, mPrototypeTable.Put(&key, aDocument)); // Put() w/o a third parameter with a destination for the
NS_IF_RELEASE(oldproto); // replaced value releases it
mPrototypeTable.Put(&key, aDocument);
return NS_OK; return NS_OK;
} }
@ -191,8 +192,7 @@ nsXULPrototypeCache::PutStyleSheet(nsICSSStyleSheet* aStyleSheet)
rv = aStyleSheet->GetURL(*getter_AddRefs(uri)); rv = aStyleSheet->GetURL(*getter_AddRefs(uri));
nsIURIKey key(uri); nsIURIKey key(uri);
nsICSSStyleSheet* oldsheet = NS_STATIC_CAST(nsICSSStyleSheet*, mStyleSheetTable.Put(&key, aStyleSheet)); mStyleSheetTable.Put(&key, aStyleSheet);
NS_IF_RELEASE(oldsheet);
return NS_OK; return NS_OK;
} }
@ -214,8 +214,7 @@ nsXULPrototypeCache::PutXBLDocument(nsIDocument *aDocument)
uri->GetSpec(&aString); uri->GetSpec(&aString);
nsStringKey key(aString); nsStringKey key(aString);
nsIDocument* olddoc = NS_STATIC_CAST(nsIDocument*, mXBLDocTable.Put(&key, aDocument)); mXBLDocTable.Put(&key, aDocument);
NS_IF_RELEASE(olddoc);
return NS_OK; return NS_OK;
} }
@ -236,8 +235,7 @@ nsXULPrototypeCache::PutXBLDocScriptAccess(nsIDocument *aDocument)
uri->GetSpec(&aString); uri->GetSpec(&aString);
nsStringKey key(aString); nsStringKey key(aString);
nsIDocument* olddoc = NS_STATIC_CAST(nsIDocument*, mScriptAccessTable.Put(&key, aDocument)); mScriptAccessTable.Put(&key, aDocument);
NS_IF_RELEASE(olddoc);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -115,21 +115,22 @@ nsLayoutHistoryState::AddState(PRUint32 aContentID,
nsIPresState* aState, nsIPresState* aState,
nsIStatefulFrame::StateType aStateType) nsIStatefulFrame::StateType aStateType)
{ {
nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * res = mStates.Put(&key, (void *) aState); /*
/* nsHashTable seems to return null when it actually added * nsSupportsHashtable::Put() returns false when no object has been
* the element in to the table. If another element was already * replaced when inserting the new one, true if it some one was.
* present in the table for the key, it seems to return the *
* element that was already present. Not sure if that was
* the intended behavior
*/ */
if (res) { PRBool replaced = mStates.Put (&key, aState);
//printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); if (replaced)
rv = NS_OK; {
// done this way by indication of warren@netscape.com [ipg]
#if 0
printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n");
#endif
} }
return rv; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -139,13 +140,15 @@ nsLayoutHistoryState::GetState(PRUint32 aContentID,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * state = nsnull; nsISupports *state = nsnull;
state = mStates.Get(&key); state = mStates.Get(&key);
if (state) { if (state) {
*aState = (nsIPresState *)state; *aState = (nsIPresState *)state;
} }
else { else {
// printf("nsLayoutHistoryState::GetState, ERROR getting History state for the key\n"); #if 0
printf("nsLayoutHistoryState::GetState, ERROR getting History state for the key\n");
#endif
*aState = nsnull; *aState = nsnull;
rv = NS_OK; rv = NS_OK;
} }
@ -158,7 +161,6 @@ nsLayoutHistoryState::RemoveState(PRUint32 aContentID,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * state = nsnull; mStates.Remove(&key);
state = mStates.Remove(&key);
return rv; return rv;
} }

Просмотреть файл

@ -115,21 +115,22 @@ nsLayoutHistoryState::AddState(PRUint32 aContentID,
nsIPresState* aState, nsIPresState* aState,
nsIStatefulFrame::StateType aStateType) nsIStatefulFrame::StateType aStateType)
{ {
nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * res = mStates.Put(&key, (void *) aState); /*
/* nsHashTable seems to return null when it actually added * nsSupportsHashtable::Put() returns false when no object has been
* the element in to the table. If another element was already * replaced when inserting the new one, true if it some one was.
* present in the table for the key, it seems to return the *
* element that was already present. Not sure if that was
* the intended behavior
*/ */
if (res) { PRBool replaced = mStates.Put (&key, aState);
//printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n"); if (replaced)
rv = NS_OK; {
// done this way by indication of warren@netscape.com [ipg]
#if 0
printf("nsLayoutHistoryState::AddState OOPS!. There was already a state in the hash table for the key\n");
#endif
} }
return rv; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -139,13 +140,15 @@ nsLayoutHistoryState::GetState(PRUint32 aContentID,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * state = nsnull; nsISupports *state = nsnull;
state = mStates.Get(&key); state = mStates.Get(&key);
if (state) { if (state) {
*aState = (nsIPresState *)state; *aState = (nsIPresState *)state;
} }
else { else {
// printf("nsLayoutHistoryState::GetState, ERROR getting History state for the key\n"); #if 0
printf("nsLayoutHistoryState::GetState, ERROR getting History state for the key\n");
#endif
*aState = nsnull; *aState = nsnull;
rv = NS_OK; rv = NS_OK;
} }
@ -158,7 +161,6 @@ nsLayoutHistoryState::RemoveState(PRUint32 aContentID,
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
HistoryKey key(aContentID, aStateType); HistoryKey key(aContentID, aStateType);
void * state = nsnull; mStates.Remove(&key);
state = mStates.Remove(&key);
return rv; return rv;
} }

Просмотреть файл

@ -2444,8 +2444,7 @@ nsEventStateManager::RegisterAccessKey(nsIFrame * aFrame, nsIContent* aContent,
if (content) { if (content) {
nsVoidKey key((void*)aKey); nsVoidKey key((void*)aKey);
nsIContent* oldContent = NS_STATIC_CAST(nsIContent*, mAccessKeys->Put(&key, content)); mAccessKeys->Put(&key, content);
NS_IF_RELEASE(oldContent);
} }
return NS_OK; return NS_OK;

Просмотреть файл

@ -126,8 +126,7 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
nsISupportsKey key(aContent); nsISupportsKey key(aContent);
if (aBinding) { if (aBinding) {
nsIXBLBinding* oldBinding = NS_STATIC_CAST(nsIXBLBinding*, mBindingTable->Put(&key, aBinding)); mBindingTable->Put (&key, aBinding);
NS_IF_RELEASE(oldBinding);
} }
else else
mBindingTable->Remove(&key); mBindingTable->Remove(&key);

Просмотреть файл

@ -132,7 +132,13 @@ nsresult nsMsgDatabase::RemoveHdrFromCache(nsIMsgDBHdr *hdr, nsMsgKey key)
nsCAutoString strKey; nsCAutoString strKey;
strKey.AppendInt(key, 10); strKey.AppendInt(key, 10);
nsStringKey hashKey(strKey.GetBuffer()); nsStringKey hashKey(strKey.GetBuffer());
nsIMsgDBHdr *removedHdr = (nsIMsgDBHdr *) m_cachedHeaders->Remove(&hashKey); // does this release, or do I have to? /*
* this does release on the held object, unless you don't
* want it to, by passing as third argument a non-null pointer
* where to store it; this way you would get the ownership
* of the reference held by the table for that object.
*/
m_cachedHeaders->Remove(&hashKey);
} }
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -609,7 +609,7 @@ nsDNSLookup::InitiateLookup(void)
// XXX remove from hashtable and release - for now // XXX remove from hashtable and release - for now
nsStringKey key(mHostName); nsStringKey key(mHostName);
(void) nsDNSService::gService->mLookups.Remove(&key); nsDNSService::gService->mLookups.Remove(&key);
#endif /* XP_UNIX */ #endif /* XP_UNIX */
@ -1149,7 +1149,6 @@ nsDNSService::GetLookupEntry(const char* hostName,
nsDNSLookup* *result) nsDNSLookup* *result)
{ {
nsresult rv; nsresult rv;
void* prev;
nsAutoMonitor mon(mMonitor); nsAutoMonitor mon(mMonitor);
@ -1176,9 +1175,11 @@ nsDNSService::GetLookupEntry(const char* hostName,
rv = lookup->Init(hostName); rv = lookup->Init(hostName);
if (NS_FAILED(rv)) goto done; if (NS_FAILED(rv)) goto done;
NS_ADDREF(lookup); NS_ADDREF(lookup); // reference for the caller
prev = mLookups.Put(&key, lookup); if (mLookups.Put(&key, lookup))
NS_ASSERTION(prev == nsnull, "already a nsDNSLookup entry"); {
NS_ASSERTION (0, "already a nsDNSLookup entry");
}
*result = lookup; *result = lookup;
done: done:

Просмотреть файл

@ -855,7 +855,7 @@ NS_IMETHODIMP nsChromeRegistry::LoadDataSource(const nsCString &aFileName,
nsCOMPtr<nsISupports> supports = do_QueryInterface(remote); nsCOMPtr<nsISupports> supports = do_QueryInterface(remote);
nsStringKey skey(key); nsStringKey skey(key);
mDataSourceTable->Put(&skey, (void*)supports.get()); mDataSourceTable->Put(&skey, supports.get());
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -52,16 +52,14 @@ nsControllerCommandManager::RegisterCommand(const PRUnichar *commandName, nsICon
{ {
nsStringKey commandKey(commandName); nsStringKey commandKey(commandName);
void* replacedCmd = mCommandsTable.Put(&commandKey, (void*)aCommand); if (mCommandsTable.Put (&commandKey, aCommand))
#if DEBUG
if (replacedCmd)
{ {
#if DEBUG
nsCAutoString msg("Replacing existing command -- "); nsCAutoString msg("Replacing existing command -- ");
msg.AppendWithConversion(commandName); msg.AppendWithConversion(commandName);
NS_WARNING(msg); NS_WARNING(msg);
}
#endif #endif
}
return NS_OK; return NS_OK;
} }
@ -71,8 +69,8 @@ nsControllerCommandManager::UnregisterCommand(const PRUnichar *commandName, nsIC
{ {
nsStringKey commandKey(commandName); nsStringKey commandKey(commandName);
void* foundCommand = mCommandsTable.Remove(&commandKey); PRBool any_object_actually_removed_p = mCommandsTable.Remove (&commandKey);
return (foundCommand) ? NS_OK : NS_ERROR_FAILURE; return any_object_actually_removed_p? NS_OK : NS_ERROR_FAILURE;
} }
@ -84,7 +82,7 @@ nsControllerCommandManager::FindCommandHandler(const PRUnichar *aCommandName, ns
*outCommand = NULL; *outCommand = NULL;
nsStringKey commandKey(aCommandName); nsStringKey commandKey(aCommandName);
void* foundCommand = mCommandsTable.Get(&commandKey); // this does the addref nsISupports* foundCommand = mCommandsTable.Get(&commandKey); // this does the addref
if (!foundCommand) return NS_ERROR_FAILURE; if (!foundCommand) return NS_ERROR_FAILURE;
*outCommand = NS_REINTERPRET_CAST(nsIControllerCommand*, foundCommand); *outCommand = NS_REINTERPRET_CAST(nsIControllerCommand*, foundCommand);

Просмотреть файл

@ -159,8 +159,9 @@ nsXULPrototypeCache::PutPrototype(nsIXULPrototypeDocument* aDocument)
rv = aDocument->GetURI(getter_AddRefs(uri)); rv = aDocument->GetURI(getter_AddRefs(uri));
nsIURIKey key(uri); nsIURIKey key(uri);
nsIXULPrototypeDocument* oldproto = NS_STATIC_CAST(nsIXULPrototypeDocument*, mPrototypeTable.Put(&key, aDocument)); // Put() w/o a third parameter with a destination for the
NS_IF_RELEASE(oldproto); // replaced value releases it
mPrototypeTable.Put(&key, aDocument);
return NS_OK; return NS_OK;
} }
@ -191,8 +192,7 @@ nsXULPrototypeCache::PutStyleSheet(nsICSSStyleSheet* aStyleSheet)
rv = aStyleSheet->GetURL(*getter_AddRefs(uri)); rv = aStyleSheet->GetURL(*getter_AddRefs(uri));
nsIURIKey key(uri); nsIURIKey key(uri);
nsICSSStyleSheet* oldsheet = NS_STATIC_CAST(nsICSSStyleSheet*, mStyleSheetTable.Put(&key, aStyleSheet)); mStyleSheetTable.Put(&key, aStyleSheet);
NS_IF_RELEASE(oldsheet);
return NS_OK; return NS_OK;
} }
@ -214,8 +214,7 @@ nsXULPrototypeCache::PutXBLDocument(nsIDocument *aDocument)
uri->GetSpec(&aString); uri->GetSpec(&aString);
nsStringKey key(aString); nsStringKey key(aString);
nsIDocument* olddoc = NS_STATIC_CAST(nsIDocument*, mXBLDocTable.Put(&key, aDocument)); mXBLDocTable.Put(&key, aDocument);
NS_IF_RELEASE(olddoc);
return NS_OK; return NS_OK;
} }
@ -236,8 +235,7 @@ nsXULPrototypeCache::PutXBLDocScriptAccess(nsIDocument *aDocument)
uri->GetSpec(&aString); uri->GetSpec(&aString);
nsStringKey key(aString); nsStringKey key(aString);
nsIDocument* olddoc = NS_STATIC_CAST(nsIDocument*, mScriptAccessTable.Put(&key, aDocument)); mScriptAccessTable.Put(&key, aDocument);
NS_IF_RELEASE(olddoc);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -42,7 +42,7 @@ nsDOMViewerObject::SetTarget(nsIRDFResource *aProperty,
nsIRDFNode *aValue) nsIRDFNode *aValue)
{ {
nsISupportsKey propKey(aProperty); nsISupportsKey propKey(aProperty);
targets.Put(&propKey, (void *)aValue); targets.Put(&propKey, aValue);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -385,8 +385,8 @@ nsObjectHashtable::RemoveAndDelete(nsHashKey *aKey)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports* // nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
static PRBool PR_CALLBACK PRBool PR_CALLBACK
_ReleaseElement(nsHashKey *aKey, void *aData, void* closure) nsSupportsHashtable::ReleaseElement(nsHashKey *aKey, void *aData, void* closure)
{ {
nsISupports* element = NS_STATIC_CAST(nsISupports*, aData); nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
NS_IF_RELEASE(element); NS_IF_RELEASE(element);
@ -395,18 +395,25 @@ _ReleaseElement(nsHashKey *aKey, void *aData, void* closure)
nsSupportsHashtable::~nsSupportsHashtable() nsSupportsHashtable::~nsSupportsHashtable()
{ {
Enumerate(_ReleaseElement, nsnull); Enumerate(ReleaseElement, nsnull);
} }
void* // Return if we overwrote something
nsSupportsHashtable::Put(nsHashKey *aKey, void *aData)
PRBool
nsSupportsHashtable::Put (nsHashKey *aKey, nsISupports* aData, nsISupports **value)
{ {
nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, aData); NS_IF_ADDREF(aData);
NS_IF_ADDREF(element); void *prev = nsHashtable::Put(aKey, aData);
return nsHashtable::Put(aKey, aData); nsISupports *old = NS_REINTERPRET_CAST(nsISupports *, prev);
if (value) // pass own the ownership to the caller
*value = old;
else // the caller doesn't care, we do
NS_IF_RELEASE(old);
return prev != nsnull;
} }
void* nsISupports *
nsSupportsHashtable::Get(nsHashKey *aKey) nsSupportsHashtable::Get(nsHashKey *aKey)
{ {
void* data = nsHashtable::Get(aKey); void* data = nsHashtable::Get(aKey);
@ -414,22 +421,25 @@ nsSupportsHashtable::Get(nsHashKey *aKey)
return nsnull; return nsnull;
nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, data); nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, data);
NS_IF_ADDREF(element); NS_IF_ADDREF(element);
return data; return element;
} }
void* // Return if we found something (useful for checks)
nsSupportsHashtable::Remove(nsHashKey *aKey)
PRBool
nsSupportsHashtable::Remove(nsHashKey *aKey, nsISupports **value)
{ {
void* data = nsHashtable::Remove(aKey); void* data = nsHashtable::Remove(aKey);
if (!data)
return nsnull;
nsISupports* element = NS_STATIC_CAST(nsISupports*, data); nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
if (value) // caller wants it
*value = element;
else // caller doesn't care, we do
NS_IF_RELEASE(element); NS_IF_RELEASE(element);
return data; return data != nsnull;
} }
static PRIntn PR_CALLBACK PRIntn PR_CALLBACK
_hashEnumerateCopy(PLHashEntry *he, PRIntn i, void *arg) nsSupportsHashtable::EnumerateCopy(PLHashEntry *he, PRIntn i, void *arg)
{ {
nsHashtable *newHashtable = (nsHashtable *)arg; nsHashtable *newHashtable = (nsHashtable *)arg;
nsISupports* element = NS_STATIC_CAST(nsISupports*, he->value); nsISupports* element = NS_STATIC_CAST(nsISupports*, he->value);
@ -447,14 +457,14 @@ nsSupportsHashtable::Clone()
nsSupportsHashtable* newHashTable = nsSupportsHashtable* newHashTable =
new nsSupportsHashtable(hashtable->nentries, threadSafe); new nsSupportsHashtable(hashtable->nentries, threadSafe);
PL_HashTableEnumerateEntries(hashtable, _hashEnumerateCopy, newHashTable); PL_HashTableEnumerateEntries(hashtable, EnumerateCopy, newHashTable);
return newHashTable; return newHashTable;
} }
void void
nsSupportsHashtable::Reset() nsSupportsHashtable::Reset()
{ {
Enumerate(_ReleaseElement, nsnull); Enumerate(ReleaseElement, nsnull);
nsHashtable::Reset(); nsHashtable::Reset();
} }

Просмотреть файл

@ -59,7 +59,7 @@ protected:
public: public:
nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE); nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE);
~nsHashtable(); virtual ~nsHashtable();
PRInt32 Count(void) { return hashtable->nentries; } PRInt32 Count(void) { return hashtable->nentries; }
PRBool Exists(nsHashKey *aKey); PRBool Exists(nsHashKey *aKey);
@ -103,17 +103,41 @@ protected:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports* // nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
class NS_COM nsSupportsHashtable : public nsHashtable { class nsISupports;
class NS_COM nsSupportsHashtable
: private nsHashtable
{
public: public:
typedef PRBool (* PR_CALLBACK EnumFunc) (nsHashKey *aKey, void *aData, void* closure);
nsSupportsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE) nsSupportsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE)
: nsHashtable(aSize, threadSafe) {} : nsHashtable(aSize, threadSafe) {}
~nsSupportsHashtable(); ~nsSupportsHashtable();
void *Put(nsHashKey *aKey, void *aData); PRInt32 Count (void)
void *Get(nsHashKey *aKey); {
void *Remove(nsHashKey *aKey); return nsHashtable::Count();
}
PRBool Exists (nsHashKey *aKey)
{
return nsHashtable::Exists (aKey);
}
PRBool Put (nsHashKey *aKey,
nsISupports *aData,
nsISupports **value = NULL);
nsISupports* Get (nsHashKey *aKey);
PRBool Remove (nsHashKey *aKey, nsISupports **value = NULL);
nsHashtable *Clone(); nsHashtable *Clone();
void Enumerate (EnumFunc aEnumFunc, void* closure = NULL)
{
nsHashtable::Enumerate (aEnumFunc, closure);
}
void Reset(); void Reset();
private:
static PRBool PR_CALLBACK ReleaseElement (nsHashKey *, void *, void *);
static PRIntn PR_CALLBACK EnumerateCopy (PLHashEntry *, PRIntn, void *);
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -100,12 +100,11 @@ NS_IMETHODIMP
nsStopwatchService::Define(const char *prop, nsISupports *initialValue) nsStopwatchService::Define(const char *prop, nsISupports *initialValue)
{ {
nsStringKey key(prop); nsStringKey key(prop);
nsCOMPtr<nsIStopwatch> prev = (nsStopwatch*)mStopwatches.Get(&key); if (mStopwatches.Put(&key, initialValue))
NS_ASSERTION(prev == nsnull, "stopwatch redefinition"); {
if (prev != nsnull) NS_ASSERTION(0, "stopwatch redefinition");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
mStopwatches.Put(&key, initialValue);
return NS_OK; return NS_OK;
} }
@ -113,12 +112,11 @@ NS_IMETHODIMP
nsStopwatchService::Undefine(const char *prop) nsStopwatchService::Undefine(const char *prop)
{ {
nsStringKey key(prop); nsStringKey key(prop);
nsCOMPtr<nsIStopwatch> prev = (nsStopwatch*)mStopwatches.Get(&key); if (!mStopwatches.Remove(&key))
NS_ASSERTION(prev != nsnull, "stopwatch undefined"); {
if (prev == nsnull) NS_ASSERTION(0, "stopwatch undefined");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
mStopwatches.Remove(&key);
return NS_OK; return NS_OK;
} }
@ -137,12 +135,11 @@ NS_IMETHODIMP
nsStopwatchService::Set(const char *prop, nsISupports *value) nsStopwatchService::Set(const char *prop, nsISupports *value)
{ {
nsStringKey key(prop); nsStringKey key(prop);
nsCOMPtr<nsISupports> prev = (nsStopwatch*)mStopwatches.Get(&key); if (!mStopwatches.Put(&key, value))
NS_ASSERTION(prev != nsnull, "stopwatch undefined"); {
if (prev == nsnull) NS_ASSERTION (0, "stopwatch undefined");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
mStopwatches.Put(&key, value);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -506,8 +506,7 @@ nsDirectoryService::Undefine(const char* prop)
if (!mHashtable->Exists(&key)) if (!mHashtable->Exists(&key))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsISupports* prevValue = (nsISupports*)mHashtable->Remove(&key); mHashtable->Remove (&key);
NS_IF_RELEASE(prevValue);
return NS_OK; return NS_OK;
} }
@ -566,7 +565,7 @@ nsDirectoryService::Get(const char* prop, const nsIID & uuid, void* *result)
if (mHashtable->Exists(&key)) if (mHashtable->Exists(&key))
{ {
nsCOMPtr<nsIFile> ourFile; nsCOMPtr<nsIFile> ourFile;
nsISupports* value = (nsISupports*)mHashtable->Get(&key); nsCOMPtr<nsISupports> value = getter_AddRefs (mHashtable->Get(&key));
if (value && NS_SUCCEEDED(value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile)))) if (value && NS_SUCCEEDED(value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile))))
{ {
@ -590,12 +589,9 @@ nsDirectoryService::Set(const char* prop, nsISupports* value)
value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile)); value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile));
if (ourFile) if (ourFile)
{ {
nsIFile* cloneFile; nsCOMPtr<nsIFile> cloneFile;
ourFile->Clone(&cloneFile); ourFile->Clone (getter_AddRefs (cloneFile));
mHashtable->Put(&key, cloneFile);
nsISupports* prevValue = (nsISupports*)mHashtable->Put(&key,
NS_STATIC_CAST(nsISupports*,cloneFile));
NS_IF_RELEASE(prevValue);
return NS_OK; return NS_OK;
} }
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

Просмотреть файл

@ -53,7 +53,7 @@ class nsDirectoryService : public nsIDirectoryService, public nsIProperties, pub
private: private:
static nsDirectoryService* mService; static nsDirectoryService* mService;
static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure); static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
nsHashtable* mHashtable; nsSupportsHashtable* mHashtable;
nsCOMPtr<nsISupportsArray> mProviders; nsCOMPtr<nsISupportsArray> mProviders;
static nsIAtom *sCurrentProcess; static nsIAtom *sCurrentProcess;