зеркало из https://github.com/mozilla/gecko-dev.git
Added nsIAllocator and implementation. Made service manager services sticky'.
This commit is contained in:
Родитель
a92dfe581a
Коммит
e14885b342
|
@ -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?
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -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__
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче