mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 715770 (part 3) - Remove nsRecyclingAllocator. r=bsmedberg.
This commit is contained in:
parent
64b08a775b
commit
b75befa8ee
@ -89,7 +89,6 @@
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIRecyclingAllocator.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsISerializable.h"
|
||||
|
@ -62,8 +62,6 @@
|
||||
COMPONENT(VARIANT, nsVariantConstructor)
|
||||
COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton)
|
||||
|
||||
COMPONENT(RECYCLINGALLOCATOR, nsRecyclingAllocatorImplConstructor)
|
||||
|
||||
COMPONENT(HASH_PROPERTY_BAG, nsHashPropertyBagConstructor)
|
||||
|
||||
COMPONENT(UUID_GENERATOR, nsUUIDGeneratorConstructor)
|
||||
|
@ -117,8 +117,6 @@ extern nsresult nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **)
|
||||
|
||||
#include "nsIOUtil.h"
|
||||
|
||||
#include "nsRecyclingAllocator.h"
|
||||
|
||||
#include "SpecialSystemDirectory.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
@ -208,8 +206,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableBase64Encoder)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsRecyclingAllocatorImpl)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHashPropertyBag, Init)
|
||||
|
||||
NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsProperties, Init)
|
||||
|
@ -65,7 +65,6 @@ CPPSRCS = \
|
||||
nsObserverService.cpp \
|
||||
nsProperties.cpp \
|
||||
nsPersistentProperties.cpp \
|
||||
nsRecyclingAllocator.cpp \
|
||||
nsStaticNameTable.cpp \
|
||||
nsStringEnumerator.cpp \
|
||||
nsSupportsArray.cpp \
|
||||
@ -107,7 +106,6 @@ EXPORTS = \
|
||||
nsIUnicharBuffer.h \
|
||||
nsMathUtils.h \
|
||||
nsObserverService.h \
|
||||
nsRecyclingAllocator.h \
|
||||
nsStaticNameTable.h \
|
||||
nsStaticAtom.h \
|
||||
nsSupportsArray.h \
|
||||
@ -132,7 +130,6 @@ XPIDLSRCS = \
|
||||
nsIPropertyBag2.idl \
|
||||
nsIWritablePropertyBag.idl \
|
||||
nsIWritablePropertyBag2.idl \
|
||||
nsIRecyclingAllocator.idl \
|
||||
nsIVariant.idl \
|
||||
nsISerializable.idl \
|
||||
nsIStringEnumerator.idl \
|
||||
|
@ -1,68 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Suresh Duddi <dp@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIMemory.idl"
|
||||
|
||||
/**
|
||||
*
|
||||
* nsIRecyclingAllocator: A wrapper for the nsRecyclingAllocator
|
||||
*
|
||||
* Holds allocations and reuses them for subsequent allocs.
|
||||
* Thread safe and uses a timer to release freelist.
|
||||
*
|
||||
* @status UNDER_DEVELOPMENT
|
||||
*/
|
||||
|
||||
[scriptable, uuid(d064a04c-9cee-4319-be31-64d565bccba9)]
|
||||
interface nsIRecyclingAllocator : nsIMemory
|
||||
{
|
||||
void init(in size_t nblocks, in size_t recycleAfter, in string id);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_RECYCLINGALLOCATOR_CID \
|
||||
{ /* ac07ed4c-bf17-4976-a15c-d2194db3b1bf */ \
|
||||
0xac07ed4c, \
|
||||
0xbf17, \
|
||||
0x4976, \
|
||||
{0xa1, 0x5c, 0xd2, 0x19, 0x4d, 0xb3, 0xb1, 0xbf} }
|
||||
|
||||
#define NS_RECYCLINGALLOCATOR_CLASSNAME "Recycling Allocator"
|
||||
|
||||
#define NS_RECYCLINGALLOCATOR_CONTRACTID "@mozilla.org/recycling-allocator;1"
|
||||
%}
|
@ -1,330 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 2001, 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Suresh Duddi <dp@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* nsRecyclingAllocator
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "nsRecyclingAllocator.h"
|
||||
#include "nsIMemory.h"
|
||||
#include "prprf.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define NS_SEC_TO_MS(s) ((s) * 1000)
|
||||
|
||||
void
|
||||
nsRecyclingAllocator::nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsRecyclingAllocator *obj = (nsRecyclingAllocator *) aClosure;
|
||||
|
||||
MutexAutoLock lock(obj->mLock);
|
||||
|
||||
if (!obj->mTouched)
|
||||
{
|
||||
obj->ClearFreeList();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear touched so the next time the timer fires we can test whether
|
||||
// the allocator was used or not.
|
||||
obj->mTouched = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsRecyclingAllocator::nsRecyclingAllocator(PRUint32 nbucket, PRUint32 recycleAfter, const char *id) :
|
||||
mMaxBlocks(nbucket), mFreeListCount(0), mFreeList(nsnull),
|
||||
mLock("nsRecyclingAllocator.mLock"),
|
||||
mRecycleTimer(nsnull), mRecycleAfter(recycleAfter), mTouched(false)
|
||||
#ifdef DEBUG
|
||||
, mId(id), mNAllocated(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRecyclingAllocator::Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
ClearFreeList();
|
||||
|
||||
// Reinitialize everything
|
||||
mMaxBlocks = nbucket;
|
||||
mRecycleAfter = recycleAfter;
|
||||
#ifdef DEBUG
|
||||
mId = id;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRecyclingAllocator::~nsRecyclingAllocator()
|
||||
{
|
||||
ClearFreeList();
|
||||
}
|
||||
|
||||
// Allocation and free routines
|
||||
void*
|
||||
nsRecyclingAllocator::Malloc(PRSize bytes, bool zeroit)
|
||||
{
|
||||
// We don't enter lock for this check. This is intentional.
|
||||
// Here is my logic: we are checking if (mFreeList). Doing this check
|
||||
// without locking can lead to unpredictable results. YES. But the effect
|
||||
// of the unpredictedness are ok. here is why:
|
||||
//
|
||||
// a) if the check returned NULL when there is stuff in freelist
|
||||
// We would just end up reallocating.
|
||||
//
|
||||
// b) if the check returned nonNULL when our freelist is empty
|
||||
// This is the more likely and dangerous case. The code for
|
||||
// FindFreeBlock() will enter lock, while (null) and return null.
|
||||
//
|
||||
// The reason why I chose to not enter lock for this check was that when
|
||||
// there are no free blocks, we don't want to impose any more overhead than
|
||||
// we already are for failing over to malloc/free.
|
||||
if (mFreeList) {
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
// Mark that we are using. This will prevent any
|
||||
// Timer based release of unused memory.
|
||||
mTouched = true;
|
||||
|
||||
Block* freeNode = mFreeList;
|
||||
Block** prevp = &mFreeList;
|
||||
|
||||
while (freeNode)
|
||||
{
|
||||
if (freeNode->bytes >= bytes)
|
||||
{
|
||||
// Found the best fit free block
|
||||
// Remove this block from free list
|
||||
*prevp = freeNode->next;
|
||||
mFreeListCount --;
|
||||
|
||||
void *data = DATA(freeNode);
|
||||
if (zeroit)
|
||||
memset(data, 0, bytes);
|
||||
return data;
|
||||
}
|
||||
|
||||
prevp = &(freeNode->next);
|
||||
freeNode = freeNode->next;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to do an allocation
|
||||
// Add 4 bytes to what we allocate to hold the bucket index
|
||||
PRSize allocBytes = bytes + NS_ALLOCATOR_OVERHEAD_BYTES;
|
||||
|
||||
// Make sure it is big enough to hold the whole block
|
||||
if (allocBytes < sizeof(Block)) allocBytes = sizeof(Block);
|
||||
|
||||
// We don't have that memory already. Allocate.
|
||||
Block *ptr = (Block *) (zeroit ? calloc(1, allocBytes) : malloc(allocBytes));
|
||||
|
||||
// Deal with no memory situation
|
||||
if (!ptr)
|
||||
return ptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
mNAllocated++;
|
||||
#endif
|
||||
|
||||
// Store size and return data portion
|
||||
ptr->bytes = bytes;
|
||||
return DATA(ptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsRecyclingAllocator::Free(void *ptr)
|
||||
{
|
||||
Block* block = DATA_TO_BLOCK(ptr);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
// Mark that we are using the allocator. This will prevent any
|
||||
// timer based release of unused memory.
|
||||
mTouched = true;
|
||||
|
||||
// Check on maximum number of blocks to keep in the freelist
|
||||
if (mFreeListCount < mMaxBlocks) {
|
||||
// Find the right spot in the sorted list.
|
||||
Block* freeNode = mFreeList;
|
||||
Block** prevp = &mFreeList;
|
||||
while (freeNode)
|
||||
{
|
||||
if (freeNode->bytes >= block->bytes)
|
||||
break;
|
||||
prevp = &(freeNode->next);
|
||||
freeNode = freeNode->next;
|
||||
}
|
||||
|
||||
// Needs to be inserted between *prevp and freeNode
|
||||
*prevp = block;
|
||||
block->next = freeNode;
|
||||
mFreeListCount ++;
|
||||
} else {
|
||||
// We are holding more than max. Failover to free
|
||||
#ifdef DEBUG_dp
|
||||
char buf[1024];
|
||||
// Warn if we are failing over to malloc/free and not storing it
|
||||
// This says we have a misdesigned memory pool. The intent was
|
||||
// once the pool was full, we would never fail over to calloc.
|
||||
PR_snprintf(buf, sizeof(buf), "nsRecyclingAllocator(%s) FAILOVER 0x%p (%d) - %d allocations, %d max\n",
|
||||
mId, (char *)ptr, block->bytes, mNAllocated, mMaxBlocks);
|
||||
NS_WARNING(buf);
|
||||
mNAllocated--;
|
||||
#endif
|
||||
free(block);
|
||||
}
|
||||
|
||||
// Set up timer for releasing memory for blocks from the freelist.
|
||||
// If this fails, then we won't have a timer to release unused
|
||||
// memory. We can live with that. Also, the next Free
|
||||
// will try again to set the timer.
|
||||
if (mRecycleAfter && !mRecycleTimer)
|
||||
{
|
||||
// known only to stuff in xpcom.
|
||||
extern nsresult NS_NewTimer(nsITimer* *aResult, nsTimerCallbackFunc aCallback, void *aClosure,
|
||||
PRUint32 aDelay, PRUint32 aType);
|
||||
|
||||
(void) NS_NewTimer(&mRecycleTimer, nsRecycleTimerCallback, this,
|
||||
NS_SEC_TO_MS(mRecycleAfter),
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
// This can fail during xpcom shutdown
|
||||
if (!mRecycleTimer)
|
||||
NS_WARNING("nsRecyclingAllocator: Creating timer failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* ClearFreeList
|
||||
*
|
||||
* Frees any bucket memory that isn't in use
|
||||
*/
|
||||
|
||||
void
|
||||
nsRecyclingAllocator::ClearFreeList()
|
||||
{
|
||||
#ifdef DEBUG_dp
|
||||
printf("DEBUG: nsRecyclingAllocator(%s) ClearFreeList (%d): ", mId, mFreeListCount);
|
||||
#endif
|
||||
// Cancel the timer, because the freelist will be forcefully cleared after this.
|
||||
// We will revive the timer on the next allocation.
|
||||
// XXX Unfortunately there is no way to Cancel and restart the same timer.
|
||||
// XXX So we pretty much kill it and create a new one later.
|
||||
if (mRecycleTimer)
|
||||
{
|
||||
mRecycleTimer->Cancel();
|
||||
NS_RELEASE(mRecycleTimer);
|
||||
}
|
||||
|
||||
// We will run through the freelist and free all blocks
|
||||
Block* node = mFreeList;
|
||||
while (node)
|
||||
{
|
||||
#ifdef DEBUG_dp
|
||||
printf("%d ", node->bytes);
|
||||
#endif
|
||||
Block *next = node->next;
|
||||
free(node);
|
||||
node = next;
|
||||
}
|
||||
mFreeList = nsnull;
|
||||
mFreeListCount = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
mNAllocated = 0;
|
||||
#endif
|
||||
#ifdef DEBUG_dp
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Wrapping the recyling allocator with nsIMemory
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// nsIMemory methods
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsRecyclingAllocatorImpl, nsIMemory, nsIRecyclingAllocator)
|
||||
|
||||
NS_IMETHODIMP_(void *)
|
||||
nsRecyclingAllocatorImpl::Alloc(PRSize size)
|
||||
{
|
||||
return nsRecyclingAllocatorImpl::Malloc(size, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void *)
|
||||
nsRecyclingAllocatorImpl::Realloc(void *ptr, PRSize size)
|
||||
{
|
||||
// XXX Not yet implemented
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsRecyclingAllocatorImpl::Free(void *ptr)
|
||||
{
|
||||
nsRecyclingAllocator::Free(ptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRecyclingAllocatorImpl::Init(size_t nbuckets, size_t recycleAfter, const char *id)
|
||||
{
|
||||
return nsRecyclingAllocator::Init((PRUint32) nbuckets, (PRUint32) recycleAfter, id);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRecyclingAllocatorImpl::HeapMinimize(bool immediate)
|
||||
{
|
||||
// XXX Not yet implemented
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRecyclingAllocatorImpl::IsLowMemory(bool *lowmemoryb_ptr)
|
||||
{
|
||||
// XXX Not yet implemented
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -1,168 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 2001, 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Suresh Duddi <dp@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* nsRecyclingAllocator
|
||||
*
|
||||
* This allocator is useful when we cycle through a small set of allocations
|
||||
* repeatedly with minimal overlap. For eg. something we do for every gif
|
||||
* file read (or) buffers required for decompression of every file from jar.
|
||||
*
|
||||
* What this does is keeps around the first set of memory allocated and
|
||||
* reuses it subsequently. If all buckets are full, this falls back to
|
||||
* malloc/free
|
||||
*
|
||||
* Uses a timer to release all memory allocated if not used for more than
|
||||
* 10 secs automatically.
|
||||
*
|
||||
* Also there is a 4 byte maintenance overhead on every allocation.
|
||||
*
|
||||
* This allocator is thread safe.
|
||||
*
|
||||
* CAVEATS: As the number of buckets increases, this allocators performance
|
||||
* will drop, as the list of freed items is a linked list sorted on size.
|
||||
*/
|
||||
|
||||
#ifndef nsRecyclingAllocator_h__
|
||||
#define nsRecyclingAllocator_h__
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIRecyclingAllocator.h"
|
||||
|
||||
#define NS_DEFAULT_RECYCLE_TIMEOUT 10 // secs
|
||||
#define NS_ALLOCATOR_OVERHEAD_BYTES (sizeof(PRSize)) // bytes
|
||||
|
||||
class nsITimer;
|
||||
class nsIMemory;
|
||||
|
||||
class nsRecyclingAllocator {
|
||||
protected:
|
||||
struct Block {
|
||||
PRSize bytes;
|
||||
Block *next;
|
||||
};
|
||||
|
||||
#define DATA(block) ((void *)(((char *)block) + NS_ALLOCATOR_OVERHEAD_BYTES))
|
||||
#define DATA_TO_BLOCK(data) ((Block *)((char *)(data) - NS_ALLOCATOR_OVERHEAD_BYTES))
|
||||
|
||||
// mMaxBlocks: Maximum number of blocks that are kept in the mFreeList for recycling
|
||||
PRUint32 mMaxBlocks;
|
||||
|
||||
// mFreeListCount: Current number of blocks in the mFreeList
|
||||
PRUint32 mFreeListCount;
|
||||
|
||||
// mFreeList: linked list of free blocks sorted by increasing order of size
|
||||
Block* mFreeList;
|
||||
|
||||
// mLock: Thread safety for the member variables:
|
||||
// mFreeList, mFreeListCount, mRecycleTimer, and mTouched
|
||||
mozilla::Mutex mLock;
|
||||
|
||||
// Timer for freeing unused memory
|
||||
nsITimer *mRecycleTimer;
|
||||
|
||||
// mRecycleAfter:
|
||||
// Allocator should be untouched for this many seconds for freeing
|
||||
// unused Blocks.
|
||||
PRUint32 mRecycleAfter;
|
||||
|
||||
// mTouched:
|
||||
// says if the allocator touched the freelist. If allocator didn't touch
|
||||
// the freelist over a time time interval, timer will call ClearFreeList()
|
||||
bool mTouched;
|
||||
|
||||
#ifdef DEBUG
|
||||
// mId:
|
||||
// a string for identifying the user of nsRecyclingAllocator
|
||||
// User mainly for debug prints
|
||||
const char *mId;
|
||||
|
||||
// mNAllocated: Number of blocks allocated
|
||||
PRInt32 mNAllocated;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
// nbucket : number of buckets to hold. Capped at NS_MAX_BUCKET
|
||||
// recycleAfter : Try recycling allocated buckets after this many seconds
|
||||
// id : a string used to identify debug prints. Will not be released.
|
||||
nsRecyclingAllocator(PRUint32 nbucket = 0, PRUint32 recycleAfter = NS_DEFAULT_RECYCLE_TIMEOUT,
|
||||
const char *id = NULL);
|
||||
~nsRecyclingAllocator();
|
||||
|
||||
nsresult Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id);
|
||||
|
||||
// Allocation and free routines
|
||||
void* Malloc(PRSize size, bool zeroit = false);
|
||||
void Free(void *ptr);
|
||||
|
||||
void* Calloc(PRUint32 items, PRSize size)
|
||||
{
|
||||
return Malloc(items * size, true);
|
||||
}
|
||||
|
||||
// ClearFreeList - Frees all blocks kept by mFreelist, and stops the timer
|
||||
void ClearFreeList();
|
||||
|
||||
protected:
|
||||
|
||||
// Timer callback to trigger unused memory
|
||||
static void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
friend void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Wrapping the recyling allocator with nsIMemory
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Wrapping the nsRecyclingAllocator with nsIMemory
|
||||
class nsRecyclingAllocatorImpl : public nsRecyclingAllocator, public nsIRecyclingAllocator {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMEMORY
|
||||
NS_DECL_NSIRECYCLINGALLOCATOR
|
||||
|
||||
nsRecyclingAllocatorImpl()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
~nsRecyclingAllocatorImpl() {}
|
||||
};
|
||||
#endif // nsRecyclingAllocator_h__
|
Loading…
Reference in New Issue
Block a user