Adding nsIMemory interface (replacement for nsIAllocator). Part of xpcom API freeze.

This commit is contained in:
warren%netscape.com 2000-06-03 07:02:20 +00:00
parent 601c80f911
commit 03ec40bf4b
8 changed files with 534 additions and 0 deletions

View File

@ -1,5 +1,6 @@
nsAgg.h
nsIAllocator.h
nsMemory.h
nsCOMPtr.h
nsCom.h
nsCWeakReference.h

View File

@ -1,4 +1,5 @@
nsISupports.idl
nsIMemory.idl
nsrootidl.idl
nsIInterfaceRequestor.idl
nsIConsoleService.idl

View File

@ -34,6 +34,7 @@ REQUIRES = xpcom
CPPSRCS = \
nsAllocator.cpp \
nsMemory.cpp \
nsDebug.cpp \
nsIInterfaceRequestor.cpp \
nsTraceRefcnt.cpp \
@ -53,6 +54,7 @@ endif
EXPORTS = \
nsAgg.h \
nsIAllocator.h \
nsMemory.h \
nsCOMPtr.h \
nsCom.h \
nsCWeakReference.h \
@ -80,6 +82,7 @@ endif
XPIDLSRCS = \
nsrootidl.idl \
nsISupports.idl \
nsIMemory.idl \
nsIInterfaceRequestor.idl \
nsIWeakReference.idl \
nsIConsoleService.idl \

View File

@ -30,6 +30,7 @@ MODULE = xpcom
EXPORTS = \
nsAgg.h \
nsIAllocator.h \
nsMemory.h \
nsCOMPtr.h \
nsCom.h \
nsCWeakReference.h \
@ -50,6 +51,7 @@ XPIDL_MODULE = xpcom_base
XPIDLSRCS = \
.\nsrootidl.idl \
.\nsIMemory.idl \
.\nsILeakDetector.idl \
.\nsIInterfaceRequestor.idl \
.\nsISupports.idl \
@ -84,6 +86,7 @@ LCFLAGS = $(LCFLAGS) -DGC_LEAK_DETECTOR
CPP_OBJS = \
.\$(OBJDIR)\nsDebug.obj \
.\$(OBJDIR)\nsAllocator.obj \
.\$(OBJDIR)\nsMemoryImpl.obj \
.\$(OBJDIR)\nsCOMPtr.obj \
.\$(OBJDIR)\nsCWeakReference.obj \
.\$(OBJDIR)\nsID.obj \

122
xpcom/base/nsIMemory.idl Normal file
View File

@ -0,0 +1,122 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/**
* <font color="#FF0000"><b> W A R N I N G
* <p>This API is currently under review in preparation for making it an
* officially supported part of the mozilla platform. Please submit comments
* to porkjockeys@mozilla.org before 6/15/00. Until that time, it is not
* advised to base commercial products on this API because it is subject to
* change. Use at your own risk!
* </b></font>
*
* @status UNDER_REVIEW
*/
#include "nsISupports.idl"
interface nsIMemoryPressureObserver;
/**
* nsIMemory: interface to allocate and deallocate memory. Also provides
* for notifications in low-memory situations.
*/
[scriptable, uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3)]
interface nsIMemory : nsISupports
{
/**
* Allocates a block of memory of a particular size. If the memory
* cannot be allocated (because of an out-of-memory condition), null
* is returned.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
[noscript, notxpcom] voidPtr alloc(in size_t 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 reallocated block of memory
*
* If ptr is null, this function behaves like malloc.
* If s is the size of the block to which ptr points, the first
* min(s, size) bytes of ptr's block are copied to the new block.
* If the allocation succeeds, ptr is freed and a pointer to the
* new block returned. If the allocation fails, ptr is not freed
* and null is returned. The returned value may be the same as ptr.
*/
[noscript, notxpcom] voidPtr realloc(in voidPtr ptr,
in size_t newSize);
/**
* Frees a block of memory. Null is a permissible value, in which case
* nothing happens.
*
* @param ptr - the block of memory to free
*/
[noscript, notxpcom] void free(in voidPtr ptr);
/**
* Attempts to shrink the heap.
*/
void heapMinimize();
/**
* Allows a memory pressure observer to be registered to provide a
* callback for low-memory situations, allowing unnecessary objects to
* be freed (e.g. flushing caches). Observers will be called either
* before alloc or realloc are about to return null, or when
* heapMinimize is called.
* @param obs - the observer to register
*/
void registerObserver(in nsIMemoryPressureObserver obs);
/**
* Allows a memory pressure observer to be unregistered.
* @param obs - the observer to unregister
*/
void unregisterObserver(in nsIMemoryPressureObserver obs);
};
/**
* nsIMemoryPressureObserver: interface for low-memory notification.
*/
[scriptable, uuid(fe6c8bd4-38e4-11d4-8cf5-0060b0fc14a3)]
interface nsIMemoryPressureObserver : nsISupports
{
const unsigned long REASON_ALLOC_FAILURE = 0;
const unsigned long REASON_HEAP_MINIMIZE = 1;
/**
* Called in response to a low-memory condition.
* @param reason - either REASON_ALLOC_FAILURE when alloc or realloc
* fails, or REASON_HEAP_MINIMIZE when heapMinimize is
* called
* @param requestedAmount - either the size requested by alloc or realloc,
* or 0 if heapMinimize was called
*/
void flushMemory(in unsigned long reason,
in size_t requestedAmount);
};

58
xpcom/base/nsMemory.h Normal file
View File

@ -0,0 +1,58 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMemory_h__
#define nsMemory_h__
#include "nsIMemory.h"
/**
* Static helper routines to manage memory. These routines allow easy access
* to xpcom's built-in (global) nsIMemory implementation, without needing
* to go through the service manager to get it. However this requires clients
* to link with the xpcom DLL.
*/
class nsMemory
{
public:
static NS_EXPORT void* Alloc(size_t size);
static NS_EXPORT void* Realloc(void* ptr, size_t size);
static NS_EXPORT void Free(void* ptr);
static NS_EXPORT nsresult HeapMinimize();
static NS_EXPORT nsresult RegisterObserver(nsIMemoryPressureObserver* obs);
static NS_EXPORT nsresult UnregisterObserver(nsIMemoryPressureObserver* obs);
static NS_EXPORT void* Clone(const void* ptr, size_t size);
static NS_EXPORT nsIMemory* GetGlobalMemoryService(); // AddRefs
};
// ProgID/CID for the global memory service:
#define NS_MEMORY_PROGID "component://mozilla/xpcom/memory-service"
#define NS_MEMORY_CLASSNAME "Global Memory Service"
#define NS_MEMORY_CID \
{ /* 30a04e40-38e7-11d4-8cf5-0060b0fc14a3 */ \
0x30a04e40, \
0x38e7, \
0x11d4, \
{0x8c, 0xf5, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
}
#endif // nsMemory_h__

294
xpcom/base/nsMemoryImpl.cpp Normal file
View File

@ -0,0 +1,294 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsMemoryImpl.h"
#include "prmem.h"
#include "nsIServiceManager.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryImpl, nsIMemory)
NS_METHOD
nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
NS_ENSURE_ARG_POINTER(aInstancePtr);
NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
nsMemoryImpl* mm = new nsMemoryImpl();
if (mm == NULL)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mm->QueryInterface(aIID, aInstancePtr);
if (NS_FAILED(rv))
delete mm;
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
#ifdef DEBUG_warren
#define NS_OUT_OF_MEMORY_TESTER
#endif
#ifdef NS_OUT_OF_MEMORY_TESTER
// flush memory one in this number of times:
#define NS_FLUSH_FREQUENCY 100000
// fail allocation one in this number of flushes:
#define NS_FAIL_FREQUENCY 10
PRUint32 gFlushFreq = 0;
PRUint32 gFailFreq = 0;
static void*
mallocator(PRSize size, PRUint32& counter, PRUint32 max)
{
if (counter++ >= max) {
counter = 0;
NS_ASSERTION(0, "about to fail allocation... watch out");
return nsnull;
}
return PR_Malloc(size);
}
static void*
reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
{
if (counter++ >= max) {
counter = 0;
NS_ASSERTION(0, "about to fail reallocation... watch out");
return nsnull;
}
return PR_Realloc(ptr, size);
}
#define MALLOC1(s) mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY)
#define REALLOC1(p, s) reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY)
#define MALLOC2(s) mallocator(s, gFailFreq, NS_FAIL_FREQUENCY)
#define REALLOC2(p, s) reallocator(p, s, gFailFreq, NS_FAIL_FREQUENCY)
#else
#define MALLOC1(s) PR_Malloc(s)
#define REALLOC1(p, s) PR_Realloc(p, s)
#define MALLOC2(s) PR_Malloc(s)
#define REALLOC2(p, s) PR_Realloc(p, s)
#endif // NS_OUT_OF_MEMORY_TESTER
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP_(void *)
nsMemoryImpl::Alloc(PRSize size)
{
nsresult rv;
void* result = MALLOC1(size);
if (result == nsnull) {
rv = FlushMemory(nsIMemoryPressureObserver::REASON_ALLOC_FAILURE, size);
if (NS_FAILED(rv)) {
NS_WARNING("FlushMemory failed");
}
else {
result = MALLOC2(size);
}
}
return result;
}
NS_IMETHODIMP_(void *)
nsMemoryImpl::Realloc(void * ptr, PRSize size)
{
nsresult rv;
void* result = REALLOC1(ptr, size);
if (result == nsnull) {
rv = FlushMemory(nsIMemoryPressureObserver::REASON_ALLOC_FAILURE, size);
if (NS_FAILED(rv)) {
NS_WARNING("FlushMemory failed");
}
else {
result = REALLOC2(ptr, size);
}
}
return result;
}
NS_IMETHODIMP_(void)
nsMemoryImpl::Free(void * ptr)
{
PR_Free(ptr);
}
NS_IMETHODIMP
nsMemoryImpl::HeapMinimize(void)
{
return FlushMemory(nsIMemoryPressureObserver::REASON_HEAP_MINIMIZE, 0);
}
NS_IMETHODIMP
nsMemoryImpl::RegisterObserver(nsIMemoryPressureObserver* obs)
{
nsresult rv;
if (mObservers.get() == nsnull) {
rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
if (NS_FAILED(rv)) return rv;
}
return mObservers->AppendElement(obs);
}
NS_IMETHODIMP
nsMemoryImpl::UnregisterObserver(nsIMemoryPressureObserver* obs)
{
NS_ASSERTION(mObservers, "never called RegisterObserver");
return mObservers->RemoveElement(obs);
}
nsresult
nsMemoryImpl::FlushMemory(PRUint32 reason, PRSize size)
{
if (mObservers.get() == nsnull)
return NS_OK;
nsresult rv;
PRUint32 count;
rv = mObservers->Count(&count);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIMemoryPressureObserver> obs;
rv = mObservers->GetElementAt(i, (nsISupports**)getter_AddRefs(obs));
if (NS_FAILED(rv)) return rv;
rv = obs->FlushMemory(reason, size);
NS_ASSERTION(NS_SUCCEEDED(rv), "call to nsIMemoryPressureObserver::FlushMemory failed");
// keep going...
}
return NS_OK;
}
nsIMemory* gMemory = nsnull;
nsresult
nsMemoryImpl::Startup()
{
return Create(nsnull, NS_GET_IID(nsIMemory), (void**)&gMemory);
}
nsresult
nsMemoryImpl::Shutdown()
{
NS_RELEASE(gMemory);
gMemory = nsnull;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsMemory static helper routines
static void
EnsureGlobalMemoryService()
{
if (gMemory) return;
nsresult rv = nsMemoryImpl::Startup();
NS_ASSERTION(NS_SUCCEEDED(rv), "nsMemoryImpl::Startup failed");
NS_ASSERTION(gMemory, "improper xpcom initialization");
}
NS_EXPORT void*
nsMemory::Alloc(PRSize size)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
return gMemory->Alloc(size);
}
NS_EXPORT void*
nsMemory::Realloc(void* ptr, PRSize size)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
return gMemory->Realloc(ptr, size);
}
NS_EXPORT void
nsMemory::Free(void* ptr)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
gMemory->Free(ptr);
}
NS_EXPORT nsresult
nsMemory::HeapMinimize(void)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
return gMemory->HeapMinimize();
}
NS_EXPORT nsresult
nsMemory::RegisterObserver(nsIMemoryPressureObserver* obs)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
return gMemory->RegisterObserver(obs);
}
NS_EXPORT nsresult
nsMemory::UnregisterObserver(nsIMemoryPressureObserver* obs)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
return gMemory->UnregisterObserver(obs);
}
NS_EXPORT void*
nsMemory::Clone(const void* ptr, PRSize size)
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
void* newPtr = gMemory->Alloc(size);
if (newPtr)
memcpy(newPtr, ptr, size);
return newPtr;
}
NS_EXPORT nsIMemory*
nsMemory::GetGlobalMemoryService()
{
if (gMemory == nsnull) {
EnsureGlobalMemoryService();
}
NS_ADDREF(gMemory);
return gMemory;
}
////////////////////////////////////////////////////////////////////////////////

52
xpcom/base/nsMemoryImpl.h Normal file
View File

@ -0,0 +1,52 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMemoryImpl_h__
#define nsMemoryImpl_h__
#include "nsMemory.h"
#include "nsISupportsArray.h"
#include "nsCOMPtr.h"
class nsMemoryImpl : public nsIMemory
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORY
nsMemoryImpl() { NS_INIT_REFCNT(); }
virtual ~nsMemoryImpl() {}
nsresult FlushMemory(PRUint32 reason, size_t size);
// called from xpcom initialization/finalization:
static nsresult Startup();
static nsresult Shutdown();
static NS_METHOD
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
protected:
nsCOMPtr<nsISupportsArray> mObservers;
};
#endif // nsMemoryImpl_h__