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
|