summaryrefslogtreecommitdiffstats
path: root/source/core/memory-pool.h
blob: 6bfded06007ca07a58c9523ba225c30767499c3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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