/*
- 编写一个内存池,在运行期间不进行动态内存分配
- 为了实现快速的内存分配,通常一个内存池分配器使用预定义大小的块。
- 这个想法类似于隔离列表,但是块的确定更加快速。
- 池分配器使用块(池)和每个块中的小块的概念进行操作。
- 每个块都有预定的大小,并对对象头进行编码,其中存储着元信息。
- 为分配器或收集器的目的所需。由于大小是预定义的,我们不需要在头中存储
- 它在头中,而只能保持对下一个对象的引用。
- 特点。
-
- 参数化的池大小
- 应考虑内存对齐
- 在初始化过程中进行块分配(或者在编译过程中更好)。
- 块的内存应该已经被预分配了
- allocate()方法向内存池索取一个空闲块
- free()方法将内存块放回内存池中
- getFreeSlots()方法用于跟踪内存池的使用情况
*/
#include <iostream>
#include <cassert>
template<typename T, const size_t NumberOfChunks>
class MemoryPool
{
public:
MemoryPool()
{
len=NumberOfChunks;
data=new T*[len];
for(size_t i=0; i<len; i++)
{
data[i]=nullptr;//还没有被占用
}
}
virtual ~MemoryPool()
{
for(size_t i=0; i<len; i++)
{
if(data[i]!=nullptr)
{
delete data[i];
}
}
delete[] data;
}
template<typename... Args>
T* allocate(Args&&... args)
{
int idx[]= {args...};
if(data[idx[0]]!=nullptr)
{
//已经被占用了
return nullptr;
}
data[idx[0]]=new T(idx[0]);
return data[idx[0]];
}
void free(T* element)
{
for(size_t i=0; i<len; i++)
{
if(data[i]==element)
{
delete data[i];
data[i]=nullptr;
}
}
}
int getFreeSlots() const
{
int ret=0;
for(size_t i=0; i<len; i++)
{
if(data[i]==nullptr)
{
ret++;
}
}
return ret;
}
private:
size_t len=0;
T** data=nullptr;
};
/*
* Dummy object to be used later
*/
class MyClass
{
public:
explicit MyClass(int i=0)
{
std::cout << "MyClass ctor: " << i << std::endl;
_my_value.my_int = i;
}
~MyClass()
{
std::cout << "MyClass dtor: " << _my_value.my_int << std::endl;
}
int foo()
{
std::cout << "MyClass foo(): " << _my_value.my_int << std::endl;
return _my_value.my_int;
}
private:
typedef struct __attribute__ ((__packed__))
{
int my_int = 0;
uint8_t my_uint8;
} MyValueType;
MyValueType _my_value;
};
int main()
{
static constexpr int PoolSize = 10;
MemoryPool<MyClass, PoolSize> MyPool;
MyClass* data[PoolSize];
for(int idx=0; idx<PoolSize-1; idx++)
{
data[idx] = MyPool.allocate(idx);
if (data[idx] != nullptr)
{
const auto ret = data[idx]->foo();
assert(ret == idx);
}
else
{
if(idx < PoolSize )
{
assert(false);
}
std::cerr << "Unable to get valid memory from Pool" << std::endl;
}
std::cout << "Available Chunks: " << MyPool.getFreeSlots() << std::endl;
}
for(int idx=0; idx<PoolSize-1; idx++)
{
MyPool.free(data[idx]);
std::cout << "Available Chunks: " << MyPool.getFreeSlots() << std::endl;
}
return 0;
}