COMMON: Added a new ObjectPool class, with matching operator new/delete overloads

svn-id: r34785
This commit is contained in:
Max Horn 2008-10-12 22:05:26 +00:00
parent 24dea3aff2
commit 95474b048a
5 changed files with 43 additions and 36 deletions

View file

@ -37,15 +37,6 @@
#define USE_HASHMAP_MEMORY_POOL
#ifdef USE_HASHMAP_MEMORY_POOL
#include "common/memorypool.h"
// FIXME: we sadly can't assume standard C++ to be present
// on every system we support, so we should get rid of this.
// The solution should be to write a simple placement new
// on our own.
// Symbian does not have <new> but the new operator
#if !defined(__SYMBIAN32__)
#include <new>
#endif
#endif
namespace Common {
@ -100,27 +91,15 @@ public:
};
#ifdef USE_HASHMAP_MEMORY_POOL
FixedSizeMemoryPool<sizeof(Node), HASHMAP_MEMORYPOOL_SIZE> _nodePool;
ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool;
Node *allocNode(const Key &key) {
void* mem = _nodePool.malloc();
return new (mem) Node(key);
return new (_nodePool) Node(key);
}
void freeNode(Node *node) {
node->~Node();
_nodePool.free(node);
_nodePool.deleteChunk(node);
}
#else
Node* allocNode(const Key &key) {
return new Node(key);
}
void freeNode(Node *node) {
delete node;
}
#endif
Node **_storage; // hashtable of size arrsize.
uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */

View file

@ -79,7 +79,7 @@ void MemoryPool::addPageToPool(const Page &page) {
_next = page.start;
}
void *MemoryPool::malloc() {
void *MemoryPool::allocChunk() {
if (!_next) // No free chunks left? Allocate a new page
allocPage();
@ -89,7 +89,7 @@ void *MemoryPool::malloc() {
return result;
}
void MemoryPool::free(void* ptr) {
void MemoryPool::freeChunk(void *ptr) {
// Add the chunk back to (the start of) the list of free chunks
*(void**)ptr = _next;
_next = ptr;

View file

@ -29,6 +29,7 @@
#include "common/scummsys.h"
#include "common/array.h"
namespace Common {
class MemoryPool {
@ -54,10 +55,12 @@ public:
MemoryPool(size_t chunkSize);
~MemoryPool();
void *malloc();
void free(void *ptr);
void *allocChunk();
void freeChunk(void *ptr);
void freeUnusedPages();
size_t getChunkSize() const { return _chunkSize; }
};
template<size_t CHUNK_SIZE, size_t NUM_INTERNAL_CHUNKS = 32>
@ -83,6 +86,33 @@ public:
FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {}
};
template<class T, size_t NUM_INTERNAL_CHUNKS = 32>
class ObjectPool : public FixedSizeMemoryPool<sizeof(T), NUM_INTERNAL_CHUNKS> {
public:
void deleteChunk(T *ptr) {
ptr->~T();
freeChunk(ptr);
}
};
} // End of namespace Common
// Provide a custom placement new operator, using an arbitrary
// MemoryPool.
//
// This *should* work with all C++ implementations, but may not.
//
// For details on using placement new for custom allocators, see e.g.
// <http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14>
inline void* operator new(size_t nbytes, Common::MemoryPool& pool) {
assert(nbytes <= pool.getChunkSize());
return pool.allocChunk();
}
inline void operator delete(void* p, Common::MemoryPool& pool) {
pool.freeChunk(p);
}
#endif

View file

@ -193,7 +193,7 @@ void String::incRefCount() const {
if (g_refCountPool == 0)
g_refCountPool = new MemoryPool(sizeof(int));
_extern._refCount = (int *)g_refCountPool->malloc();
_extern._refCount = (int *)g_refCountPool->allocChunk();
*_extern._refCount = 2;
} else {
++(*_extern._refCount);
@ -212,7 +212,7 @@ void String::decRefCount(int *oldRefCount) {
// and the ref count storage.
if (oldRefCount) {
assert(g_refCountPool);
g_refCountPool->free(oldRefCount);
g_refCountPool->freeChunk(oldRefCount);
}
free(_str);

View file

@ -51,7 +51,7 @@ namespace Common {
#define MAX_XML_DEPTH 8
#define XML_KEY(keyName) {\
lay = new CustomXMLKeyLayout;\
lay = new CustomXMLKeyLayout;\
lay->callback = (&kLocalParserName::parserCallback_##keyName);\
layout.top()->children[#keyName] = lay;\
layout.push(lay); \
@ -169,16 +169,14 @@ public:
XMLKeyLayout *layout;
};
FixedSizeMemoryPool<sizeof(ParserNode), MAX_XML_DEPTH> _nodePool;
ObjectPool<ParserNode, MAX_XML_DEPTH> _nodePool;
ParserNode *allocNode() {
void* mem = _nodePool.malloc();
return new (mem) ParserNode;
return new (_nodePool) ParserNode;
}
void freeNode(ParserNode *node) {
node->~ParserNode();
_nodePool.free(node);
_nodePool.deleteChunk(node);
}
/**