内存池与内存块
#include <iostream>
using namespace std;
constexpr int MEMORYPOOL_ALIGNMENT = 8; //对齐长度
// 内存块
template<typename _T>
struct MemoryBlock {
int nSize; //内存块大小,以字节为单位
int nFree; //内存块剩余可分配单位
int nFirst; //首个剩余单位序号
MemoryBlock* pNext; //指向下一个内存块的指针
char aData[1]; //内存空间开始位置标记
//constructor
MemoryBlock(int nUnitSize, // 存储单位大小,sizeof T
int nUnitAmount) : // 内存块规模,以 存储单位 为单位计算
nSize(nUnitAmount * nUnitSize), nFree(nUnitAmount - 1), nFirst(1), pNext(nullptr) {
//第一个单位在调用构造函数时分配,故nFree需要减1
//下一个可分配单位序号记录于当前单元的前两个字节
char *ppDate = aData;
cout << "the head ptr of memory ppDate = " << (int)*ppDate << endl;
for(int i = 1; i < nUnitAmount; ++i) {
//在 当前存储单位存储下一个可分配单位的序号
(*(uint16_t*)ppDate) = i;//short --- 16
cout << "the next available of memory is :" << (int)*ppDate << endl;
ppDate += nUnitSize; //指向下一个单位
}
cout << "===========================call MemoryBlock constructor\n";
}
// overload
void* operator new(size_t, int nUnitSize, int nUnitAmount) {
//内存空间长度为memoryBlock对象加存储空间总长度
return ::operator new(sizeof(MemoryBlock) + nUnitAmount * nUnitSize);
}
void operator delete(void *pBlock) {
::operator delete(pBlock);
cout << "================================call MemoryBlock destructor\n";
}
};
// 内存池
template<typename _T>
struct MemoryPool {
int nInitSize; //第一次分配大小
int nGrowSize; //增量大小
int nUnitSize; // 存储单位大小
MemoryBlock<_T> *pBlock;
MemoryPool(int _nGrowSize = 10, int _nInitSize = 3)
: nInitSize(_nInitSize), nGrowSize(_nGrowSize), pBlock(nullptr), nUnitSize(sizeof(_T)) {
cout << "==========================call MemoryPool constructor\n";
//存储块大小调整
auto _size = sizeof(_T);
if(_size > 4) {
nUnitSize = (_size + MEMORYPOOL_ALIGNMENT - 1) & ~(MEMORYPOOL_ALIGNMENT - 1);
}
else if(_size < 2) {
nUnitSize = 2;
}
else
nUnitSize = 4;
}
~MemoryPool() {
MemoryBlock<_T> * pMyBlock = pBlock;
while(pMyBlock != nullptr) {
pMyBlock = pMyBlock->pNext;
delete pMyBlock;
}
cout << "================================call MemoryPool destructor\n";
}
void *allocate(size_t num) { //typename Allocator<_T>::const_pointer hint = 0
for(int i = 0; i < num; ++i) {
if(pBlock == nullptr) {
//create memoryBlock
pBlock = (MemoryBlock<_T>*) new (nUnitSize, nInitSize) MemoryBlock<_T>(nUnitSize, nInitSize);
return (void *)pBlock->aData;
}
//找到合适的内存块
MemoryBlock<_T> *pMyBlock = pBlock;
while(pMyBlock != nullptr && pMyBlock->nFree == 0) pMyBlock = pMyBlock->pNext;
if(pMyBlock != nullptr) {
cout << "找到内存空间, first = " << pMyBlock->nFirst << endl;
char *pFree = pMyBlock->aData + pMyBlock->nFirst * nUnitSize;
pMyBlock->nFirst = *((uint16_t *)pFree);
pMyBlock->nFree--;
return (void *)pFree;
}
else {
//没有找到,说明内存块已经用完
if(nGrowSize == 0) return NULL;
cout << "allocate new memoryBlock\n";
pMyBlock = (MemoryBlock<_T>*) new (nUnitSize, nGrowSize) MemoryBlock<_T> (nUnitSize, nGrowSize);
//失败返回
if(pMyBlock == nullptr) return NULL;
//成功的话插入链表
pMyBlock->pNext = pBlock;
pBlock = pMyBlock;
return (void *)pMyBlock->aData;
}
}
}
void free(void *pFree) {
cout << "relese room\n";
//找到内存块
MemoryBlock<_T> * pMyBlock = pBlock;
MemoryBlock<_T> * preBlock = nullptr;
while (pMyBlock != nullptr && (pBlock->aData > pFree || pMyBlock->aData + pMyBlock->nSize)) {
preBlock = pMyBlock;
pMyBlock = pMyBlock->next;
}
//
if(pMyBlock != nullptr) {
//修改数组链表
*((uint16_t*)pFree) = pMyBlock->nFirst;
pMyBlock->nFirst = (uint16_t)((uint32_t)pFree - (uint32_t)pMyBlock->aData) / nUnitSize;
pMyBlock->nFree++;
//是否需要向OS释放内存
if(pMyBlock->nSize == pMyBlock->nFree * nUnitSize) {
//delete node
delete pMyBlock;
}
else {
//将block插入队首
preBlock = pMyBlock->pNext;
pMyBlock->pNext = nullptr;
pBlock = pMyBlock;
}
}
}
};
class User {
int s;
double s1;
double s3;
public:
User(int x) : s(x) {
cout << "*********************call User constructor\n";
}
int get() const { return s; };
~User() {
cout << "************************call User destructor\n";
}
};
int main() {
MemoryPool<User> pool;
User *dp1 = (User *)pool.allocate(1);
cout << "dp1 = " << dp1 << endl;
new (dp1) User (1111);
cout << "the value of object is " << dp1->get() << endl;
User *dp2 = (User *)pool.allocate(1);
cout << "dp2 = " << dp2 << endl;
new (dp2) User (2222);
cout << "the value of object is " << dp2->get() << endl;
User *dp3 = (User *)pool.allocate(1);
cout << "dp3 = " << dp3 << endl;
new (dp3) User (3333);
cout << "the value of object is " << dp3->get() << endl;
User *dp4 = (User *)pool.allocate(1);
cout << "dp4 = " << dp4 << endl;
new (dp4) User (4444);
cout << "the value of object is " << dp4->get() << endl;
User *dp5 = (User *)pool.allocate(1);
cout << "dp5 = " << dp5 << endl;
new (dp5) User (5555);
cout << "the value of object is " << dp5->get() << endl;
return 0;
}