COMMON: Added a new ObjectPool class, with matching operator new/delete overloads
svn-id: r34785
This commit is contained in:
parent
24dea3aff2
commit
95474b048a
5 changed files with 43 additions and 36 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue