summaryrefslogtreecommitdiffstats
path: root/source/core/memory-pool.h
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-09 11:34:21 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-09 13:44:59 -0700
commitfcf83dbf9effab3bd98bad2b83b2468b7eb05cfd (patch)
tree41047c94883b86ec085a81597391ce3ef557cd43 /source/core/memory-pool.h
parent52e8d4b9a27ab0060f874c3a63ab531847be35c0 (diff)
Initial import of code.
Diffstat (limited to 'source/core/memory-pool.h')
-rw-r--r--source/core/memory-pool.h126
1 files changed, 126 insertions, 0 deletions
diff --git a/source/core/memory-pool.h b/source/core/memory-pool.h
new file mode 100644
index 000000000..6bfded060
--- /dev/null
+++ b/source/core/memory-pool.h
@@ -0,0 +1,126 @@
+#ifndef CORE_LIB_MEMORY_POOL_H
+#define CORE_LIB_MEMORY_POOL_H
+
+#include "basic.h"
+#include "int-set.h"
+
+namespace CoreLib
+{
+ namespace Basic
+ {
+ struct MemoryBlockFields
+ {
+ unsigned int Occupied : 1;
+ unsigned int Order : 31;
+ };
+ struct FreeListNode
+ {
+ FreeListNode * PrevPtr = nullptr, *NextPtr = nullptr;
+ };
+ class MemoryPool
+ {
+ private:
+ static const int MaxLevels = 32;
+ int blockSize = 0, log2BlockSize = 0;
+ int numLevels = 0;
+ int bytesAllocated = 0;
+ int bytesWasted = 0;
+ unsigned char * buffer = nullptr;
+ FreeListNode * freeList[MaxLevels];
+ IntSet used;
+ int AllocBlock(int level);
+ void FreeBlock(unsigned char * ptr, int level);
+ public:
+ MemoryPool(unsigned char * buffer, int log2BlockSize, int numBlocks);
+ MemoryPool() = default;
+ void Init(unsigned char * buffer, int log2BlockSize, int numBlocks);
+ unsigned char * Alloc(int size);
+ void Free(unsigned char * ptr, int size);
+ };
+
+ class OutofPoolMemoryException : public Exception
+ {};
+
+ template<typename T, int PoolSize>
+ class ObjectPool
+ {
+ static const int ObjectSize = sizeof(T) < 8 ? 8 : sizeof(T);
+ private:
+ struct FreeList
+ {
+ FreeList* Next;
+ };
+ FreeList * freeList = nullptr;
+ int allocPtr = 0;
+ int poolSize = 0;
+ void * buffer = 0;
+ T * GetFreeObject()
+ {
+ if (freeList)
+ {
+ auto rs = (T*)freeList;
+ freeList = freeList->Next;
+ return rs;
+ }
+ return nullptr;
+ }
+ public:
+ ObjectPool()
+ {
+ freeList = nullptr;
+ allocPtr = 0;
+ buffer = malloc(PoolSize * ObjectSize);
+ }
+
+ void Close()
+ {
+ free(buffer);
+ }
+
+ void Free(T * obj)
+ {
+ auto newList = (FreeList*)obj;
+ newList->Next = freeList;
+ freeList = newList;
+ }
+
+ void * Buffer()
+ {
+ return buffer;
+ }
+
+ T * Alloc()
+ {
+ auto rs = GetFreeObject();
+ if (!rs)
+ {
+ if (allocPtr < PoolSize)
+ {
+ rs = (T*)buffer + allocPtr;
+ allocPtr++;
+ }
+ }
+ if (!rs)
+ {
+ throw OutofPoolMemoryException();
+ }
+ return rs;
+ }
+ };
+ };
+
+#define USE_POOL_ALLOCATOR(T, PoolSize) \
+ private:\
+ static CoreLib::ObjectPool<T, PoolSize> _pool;\
+ public:\
+ void * operator new(std::size_t) { return _pool.Alloc(); } \
+ void operator delete(void * ptr) {_pool.Free((T*)ptr); }\
+ int GetObjectId() { return (int)(this - (T*)_pool.Buffer()); }\
+ static void ClosePool();
+#define IMPL_POOL_ALLOCATOR(T, PoolSize) \
+ CoreLib::ObjectPool<T, PoolSize> T::_pool;\
+ void T::ClosePool() { _pool.Close(); }
+
+}
+
+#endif \ No newline at end of file