aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2008-10-12 22:05:26 +0000
committerMax Horn2008-10-12 22:05:26 +0000
commit95474b048aa742f500f276f782e9998eccfce8d9 (patch)
treed1724aeabc9af30742c64a2cb85e27970bfd648a
parent24dea3aff2e635f19695ac680a33bb6738bbad97 (diff)
downloadscummvm-rg350-95474b048aa742f500f276f782e9998eccfce8d9.tar.gz
scummvm-rg350-95474b048aa742f500f276f782e9998eccfce8d9.tar.bz2
scummvm-rg350-95474b048aa742f500f276f782e9998eccfce8d9.zip
COMMON: Added a new ObjectPool class, with matching operator new/delete overloads
svn-id: r34785
-rw-r--r--common/hashmap.h27
-rw-r--r--common/memorypool.cpp4
-rw-r--r--common/memorypool.h34
-rw-r--r--common/str.cpp4
-rw-r--r--common/xmlparser.h10
5 files changed, 43 insertions, 36 deletions
diff --git a/common/hashmap.h b/common/hashmap.h
index 81f5ee84b4..bbc227b3ae 100644
--- a/common/hashmap.h
+++ b/common/hashmap.h
@@ -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 */
diff --git a/common/memorypool.cpp b/common/memorypool.cpp
index 12307ba5d6..b117d13931 100644
--- a/common/memorypool.cpp
+++ b/common/memorypool.cpp
@@ -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;
diff --git a/common/memorypool.h b/common/memorypool.h
index dd2e8f13a4..22326941f3 100644
--- a/common/memorypool.h
+++ b/common/memorypool.h
@@ -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
diff --git a/common/str.cpp b/common/str.cpp
index 303ed7bfac..00e88bfc3b 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -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);
diff --git a/common/xmlparser.h b/common/xmlparser.h
index cd2580b448..31ba4e594e 100644
--- a/common/xmlparser.h
+++ b/common/xmlparser.h
@@ -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);
}
/**