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

This commit is contained in:
warren%netscape.com 1999-01-27 02:02:22 +00:00
Родитель a92dfe581a
Коммит e14885b342
14 изменённых файлов: 714 добавлений и 137 удалений

129
xpcom/base/nsAllocator.cpp Normal file
Просмотреть файл

@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#include "nsAllocator.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIAllocatorIID, NS_IALLOCATOR_IID);
nsAllocator::nsAllocator(nsISupports* outer)
{
NS_INIT_AGGREGATED(outer);
}
nsAllocator::~nsAllocator(void)
{
}
NS_IMPL_AGGREGATED(nsAllocator);
NS_METHOD
nsAllocator::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIAllocatorIID) ||
aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_METHOD
nsAllocator::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
if (outer && !aIID.Equals(kISupportsIID))
return NS_NOINTERFACE; // XXX right error?
nsAllocator* mm = new nsAllocator(outer);
if (mm == NULL)
return NS_ERROR_OUT_OF_MEMORY;
mm->AddRef();
if (aIID.Equals(kISupportsIID))
*aInstancePtr = mm->GetInner();
else
*aInstancePtr = mm;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_METHOD_(void*)
nsAllocator::Alloc(PRUint32 size)
{
return PR_Malloc(size);
}
NS_METHOD_(void*)
nsAllocator::Realloc(void* ptr, PRUint32 size)
{
return PR_Realloc(ptr, size);
}
NS_METHOD
nsAllocator::Free(void* ptr)
{
PR_Free(ptr);
return NS_OK;
}
NS_METHOD
nsAllocator::HeapMinimize(void)
{
#ifdef XP_MAC
// This used to live in the memory allocators no Mac, but does no more
// Needs to be hooked up in the new world.
// CallCacheFlushers(0x7fffffff);
#endif
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
nsAllocatorFactory::nsAllocatorFactory(void)
{
}
nsAllocatorFactory::~nsAllocatorFactory(void)
{
}
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
NS_IMPL_ISUPPORTS(nsAllocatorFactory, kIFactoryIID);
NS_METHOD
nsAllocatorFactory::CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult)
{
return nsAllocator::Create(aOuter, aIID, aResult);
}
NS_METHOD
nsAllocatorFactory::LockFactory(PRBool aLock)
{
return NS_OK; // XXX what?
}
////////////////////////////////////////////////////////////////////////////////

93
xpcom/base/nsAllocator.h Normal file
Просмотреть файл

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#ifndef nsAllocator_h__
#define nsAllocator_h__
#include "nsIAllocator.h"
#include "prmem.h"
#include "nsAgg.h"
class nsAllocator : nsIAllocator {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size);
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size);
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr);
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void);
////////////////////////////////////////////////////////////////////////////
nsAllocator(nsISupports* outer);
virtual ~nsAllocator(void);
NS_DECL_AGGREGATED
static NS_METHOD
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
};
////////////////////////////////////////////////////////////////////////////////
#include "nsIFactory.h"
class nsAllocatorFactory : nsIFactory {
public:
NS_IMETHOD CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsAllocatorFactory(void);
~nsAllocatorFactory(void);
NS_DECL_ISUPPORTS
};
////////////////////////////////////////////////////////////////////////////////
#endif // nsAllocator_h__

82
xpcom/base/nsIAllocator.h Normal file
Просмотреть файл

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIAllocator_h___
#define nsIAllocator_h___
#include "nsISupports.h"
/**
* Unlike IMalloc, this interface returns nsresults and doesn't
* implement the problematic GetSize and DidAlloc routines.
*/
class nsIAllocator : public nsISupports {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size) = 0;
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size) = 0;
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr) = 0;
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void) = 0;
};
#define NS_IALLOCATOR_IID \
{ /* 56def700-b1b9-11d2-8177-006008119d7a */ \
0x56def700, \
0xb1b9, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
// To get the global memory manager service:
#define NS_ALLOCATOR_CID \
{ /* aafe6770-b1bb-11d2-8177-006008119d7a */ \
0xaafe6770, \
0xb1bb, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
////////////////////////////////////////////////////////////////////////////////
#endif /* nsIAllocator_h___ */

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

@ -86,28 +86,6 @@ public:
}
};
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);
}
};
#ifdef USE_NSREG
#define USE_REGISTRY
@ -288,7 +266,7 @@ nsresult nsRepository::FindFactory(const nsCID &aClass,
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *entry = (FactoryEntry*) factories->Get(&key);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
@ -452,7 +430,7 @@ nsresult nsRepository::RegisterFactory(const nsCID &aClass,
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
factories->Put(&key, new FactoryEntry(aClass, aFactory, NULL));
PR_ExitMonitor(monitor);
@ -499,7 +477,7 @@ nsresult nsRepository::RegisterFactory(const nsCID &aClass,
else
#endif
{
IDKey key(aClass);
nsIDKey key(aClass);
factories->Put(&key, new FactoryEntry(aClass, NULL, aLibrary));
}
@ -530,7 +508,7 @@ nsresult nsRepository::UnregisterFactory(const nsCID &aClass,
if (old == aFactory) {
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *entry = (FactoryEntry *) factories->Remove(&key);
delete entry;
@ -560,7 +538,7 @@ nsresult nsRepository::UnregisterFactory(const nsCID &aClass,
delete [] buf;
}
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *old = (FactoryEntry *) factories->Get(&key);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;

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

@ -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

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

@ -53,4 +53,30 @@ public:
void Enumerate(nsHashtableEnumFunc aEnumFunc, void* closure = NULL);
};
////////////////////////////////////////////////////////////////////////////////
#include "nsID.h"
class nsIDKey: public nsHashKey {
private:
nsID id;
public:
nsIDKey(const nsID &aID) {
id = aID;
}
PRUint32 HashValue(void) const {
return id.m0;
}
PRBool Equals(const nsHashKey *aKey) const {
return (id.Equals(((const nsIDKey *) aKey)->id));
}
nsHashKey *Clone(void) const {
return new nsIDKey(id);
}
};
#endif

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

@ -20,7 +20,7 @@ IGNORE_MANIFEST=1
DEPTH=..\..
EXPORTS = \
nsCOMPtr.h \
nsCOMPtr.h \
nsAgg.h \
nsCom.h \
nsDebug.h \
@ -41,6 +41,7 @@ EXPORTS = \
nsXPComFactory.h \
nsXPComCIID.h \
nsIEventQueueService.h \
nsIAllocator.h \
$(NULL)
MODULE = xpcom

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

@ -53,4 +53,30 @@ public:
void Enumerate(nsHashtableEnumFunc aEnumFunc, void* closure = NULL);
};
////////////////////////////////////////////////////////////////////////////////
#include "nsID.h"
class nsIDKey: public nsHashKey {
private:
nsID id;
public:
nsIDKey(const nsID &aID) {
id = aID;
}
PRUint32 HashValue(void) const {
return id.m0;
}
PRBool Equals(const nsHashKey *aKey) const {
return (id.Equals(((const nsIDKey *) aKey)->id));
}
nsHashKey *Clone(void) const {
return new nsIDKey(id);
}
};
#endif

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

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIAllocator_h___
#define nsIAllocator_h___
#include "nsISupports.h"
/**
* Unlike IMalloc, this interface returns nsresults and doesn't
* implement the problematic GetSize and DidAlloc routines.
*/
class nsIAllocator : public nsISupports {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size) = 0;
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size) = 0;
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr) = 0;
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void) = 0;
};
#define NS_IALLOCATOR_IID \
{ /* 56def700-b1b9-11d2-8177-006008119d7a */ \
0x56def700, \
0xb1b9, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
// To get the global memory manager service:
#define NS_ALLOCATOR_CID \
{ /* aafe6770-b1bb-11d2-8177-006008119d7a */ \
0xaafe6770, \
0xb1bb, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
////////////////////////////////////////////////////////////////////////////////
#endif /* nsIAllocator_h___ */

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

@ -59,6 +59,7 @@ CPPSRCS = \
nsTraceRefcnt.cpp \
nsXPComFactory.cpp \
nsEventQueueService.cpp \
nsAllocator.cpp \
$(NULL)
CPP_OBJS = \
@ -71,6 +72,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsTraceRefcnt.obj \
.\$(OBJDIR)\nsXPComFactory.obj \
.\$(OBJDIR)\nsEventQueueService.obj \
.\$(OBJDIR)\nsAllocator.obj \
$(NULL)
MODULE = xpcom

129
xpcom/src/nsAllocator.cpp Normal file
Просмотреть файл

@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#include "nsAllocator.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIAllocatorIID, NS_IALLOCATOR_IID);
nsAllocator::nsAllocator(nsISupports* outer)
{
NS_INIT_AGGREGATED(outer);
}
nsAllocator::~nsAllocator(void)
{
}
NS_IMPL_AGGREGATED(nsAllocator);
NS_METHOD
nsAllocator::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIAllocatorIID) ||
aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_METHOD
nsAllocator::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
if (outer && !aIID.Equals(kISupportsIID))
return NS_NOINTERFACE; // XXX right error?
nsAllocator* mm = new nsAllocator(outer);
if (mm == NULL)
return NS_ERROR_OUT_OF_MEMORY;
mm->AddRef();
if (aIID.Equals(kISupportsIID))
*aInstancePtr = mm->GetInner();
else
*aInstancePtr = mm;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_METHOD_(void*)
nsAllocator::Alloc(PRUint32 size)
{
return PR_Malloc(size);
}
NS_METHOD_(void*)
nsAllocator::Realloc(void* ptr, PRUint32 size)
{
return PR_Realloc(ptr, size);
}
NS_METHOD
nsAllocator::Free(void* ptr)
{
PR_Free(ptr);
return NS_OK;
}
NS_METHOD
nsAllocator::HeapMinimize(void)
{
#ifdef XP_MAC
// This used to live in the memory allocators no Mac, but does no more
// Needs to be hooked up in the new world.
// CallCacheFlushers(0x7fffffff);
#endif
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
nsAllocatorFactory::nsAllocatorFactory(void)
{
}
nsAllocatorFactory::~nsAllocatorFactory(void)
{
}
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
NS_IMPL_ISUPPORTS(nsAllocatorFactory, kIFactoryIID);
NS_METHOD
nsAllocatorFactory::CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult)
{
return nsAllocator::Create(aOuter, aIID, aResult);
}
NS_METHOD
nsAllocatorFactory::LockFactory(PRBool aLock)
{
return NS_OK; // XXX what?
}
////////////////////////////////////////////////////////////////////////////////

93
xpcom/src/nsAllocator.h Normal file
Просмотреть файл

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#ifndef nsAllocator_h__
#define nsAllocator_h__
#include "nsIAllocator.h"
#include "prmem.h"
#include "nsAgg.h"
class nsAllocator : nsIAllocator {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size);
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size);
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr);
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void);
////////////////////////////////////////////////////////////////////////////
nsAllocator(nsISupports* outer);
virtual ~nsAllocator(void);
NS_DECL_AGGREGATED
static NS_METHOD
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
};
////////////////////////////////////////////////////////////////////////////////
#include "nsIFactory.h"
class nsAllocatorFactory : nsIFactory {
public:
NS_IMETHOD CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsAllocatorFactory(void);
~nsAllocatorFactory(void);
NS_DECL_ISUPPORTS
};
////////////////////////////////////////////////////////////////////////////////
#endif // nsAllocator_h__

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

@ -86,28 +86,6 @@ public:
}
};
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);
}
};
#ifdef USE_NSREG
#define USE_REGISTRY
@ -288,7 +266,7 @@ nsresult nsRepository::FindFactory(const nsCID &aClass,
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *entry = (FactoryEntry*) factories->Get(&key);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
@ -452,7 +430,7 @@ nsresult nsRepository::RegisterFactory(const nsCID &aClass,
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
factories->Put(&key, new FactoryEntry(aClass, aFactory, NULL));
PR_ExitMonitor(monitor);
@ -499,7 +477,7 @@ nsresult nsRepository::RegisterFactory(const nsCID &aClass,
else
#endif
{
IDKey key(aClass);
nsIDKey key(aClass);
factories->Put(&key, new FactoryEntry(aClass, NULL, aLibrary));
}
@ -530,7 +508,7 @@ nsresult nsRepository::UnregisterFactory(const nsCID &aClass,
if (old == aFactory) {
PR_EnterMonitor(monitor);
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *entry = (FactoryEntry *) factories->Remove(&key);
delete entry;
@ -560,7 +538,7 @@ nsresult nsRepository::UnregisterFactory(const nsCID &aClass,
delete [] buf;
}
IDKey key(aClass);
nsIDKey key(aClass);
FactoryEntry *old = (FactoryEntry *) factories->Get(&key);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;

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

@ -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