Added nsIAllocator and implementation. Made service manager services sticky'.

git-svn-id: svn://10.0.0.236/trunk@18690 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
warren%netscape.com
1999-01-27 02:02:22 +00:00
parent 78f31b3921
commit eef8571946
14 changed files with 714 additions and 137 deletions

View File

@@ -21,29 +21,6 @@
#include "prcmon.h"
#include "prthread.h" /* XXX: only used for the NSPR initialization hack (rick) */
// XXX move to nsID.h or nsHashtable.h? (copied from nsRepository.cpp)
class IDKey: public nsHashKey {
private:
nsID id;
public:
IDKey(const nsID &aID) {
id = aID;
}
PRUint32 HashValue(void) const {
return id.m0;
}
PRBool Equals(const nsHashKey *aKey) const {
return (id.Equals(((const IDKey *) aKey)->id));
}
nsHashKey *Clone(void) const {
return new IDKey(id);
}
};
class nsServiceEntry {
public:
@@ -57,11 +34,12 @@ public:
const nsCID& mClassID;
nsISupports* mService;
nsVector* mListeners; // nsVector<nsIShutdownListener>
PRBool mShuttingDown;
};
nsServiceEntry::nsServiceEntry(const nsCID& cid, nsISupports* service)
: mClassID(cid), mService(service), mListeners(NULL)
: mClassID(cid), mService(service), mListeners(NULL), mShuttingDown(PR_FALSE)
{
}
@@ -216,7 +194,7 @@ nsServiceManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
(void)PR_GetCurrentThread();
PR_CEnterMonitor(this);
IDKey key(aClass);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
if (entry) {
@@ -226,6 +204,14 @@ nsServiceManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
err = entry->AddListener(shutdownListener);
if (err == NS_OK) {
*result = service;
// If someone else requested the service to be shut down,
// and we just asked to get it again before it could be
// released, then cancel their shutdown request:
if (entry->mShuttingDown) {
entry->mShuttingDown = PR_FALSE;
service->AddRef(); // Released in ShutdownService
}
}
}
}
@@ -242,10 +228,8 @@ nsServiceManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
err = entry->AddListener(shutdownListener);
if (err == NS_OK) {
mServices->Put(&key, entry);
service->AddRef(); // Add a extra ref so that the service is not freed for now.
// Should fix it later depending on Mem pressure API or some
// daemon killer thread.
*result = service;
service->AddRef(); // Released in ShutdownService
}
else {
service->Release();
@@ -261,12 +245,12 @@ nsServiceManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
nsresult
nsServiceManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener)
nsIShutdownListener* shutdownListener)
{
nsresult err = NS_OK;
PR_CEnterMonitor(this);
IDKey key(aClass);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
NS_ASSERTION(entry, "service not found");
@@ -274,18 +258,12 @@ nsServiceManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
if (entry) {
err = entry->RemoveListener(shutdownListener);
// XXX Is this too aggressive? Maybe we should have a memory
// pressure API that releases services if they're not in use so
// that we don't thrash.(warren)
nsrefcnt cnt = service->Release();
#if 0
// Turns out to be too aggressive. Stanley reported that he always gets a new copy
// of service.So do not remove it. Also one cannot depend return value of Release as per COM! (sudu)
if (err == NS_OK && cnt == 0) {
mServices->Remove(&key);
delete entry;
err = nsRepository::FreeLibraries();
}
#endif
}
PR_CExitMonitor(this);
@@ -298,18 +276,19 @@ nsServiceManagerImpl::ShutdownService(const nsCID& aClass)
nsresult err = NS_OK;
PR_CEnterMonitor(this);
IDKey key(aClass);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
if (entry == NULL) {
err = NS_ERROR_SERVICE_NOT_FOUND;
}
else {
entry->mService->AddRef();
err = entry->NotifyListeners();
nsrefcnt cnt = entry->mService->Release();
err = entry->NotifyListeners(); // break the cycles
entry->mShuttingDown = PR_TRUE;
nsrefcnt cnt = entry->mService->Release(); // AddRef in GetService
if (err == NS_OK && cnt == 0) {
mServices->Remove(&key);
delete entry;
err = nsRepository::FreeLibraries();
}
else