C++实现内存池MemoryPool 包含单线程和多线程

             内存池是在系统提供的malloc函数和free函数无法满足性能要求的情况下,一个有效的解决方案。

             我的设计思路如下: 用一个二维链表实现,第一个维度为block,用于区分不同的大小所对应的链区。第二个维度为chunk,一个block包含若干个chunk,一个chunk单位是我们的分配对象。通过指定大小来分配空间,通过chunk指针来设置回收。

             存储结构图如下:

                    在这里,使用void*来表示分配的内存,所有寻找内存的变量都在chunk中。

                    另外,已经实现了并发的多线程测试,在malloc和free的代码段使用关键代码CRITICAL_SECTION锁定。

                   话不多说,上代码。

相关头文件:MemoryPool.h

#include "windows.h"
#include <fstream>
#include <vector>
using namespace::std;


//基类 块类和块下链类都继承Node类
class Node
{
public:
Node(){};
~Node(){};
   void setSize(int c) ;
    int getSize();
protected:
int size;
};


class ChunkNode :public Node//分配块
{
public:
  ChunkNode(int n);
  ~ChunkNode(){};
 void setUse(int u);
 void setNext(ChunkNode *c);
 int getUse();
 void* init();
 void* getMem();
 ChunkNode *getNext();
 ChunkNode *findByNum(int i);
 
 //记录块序
 int numC;
 int numB;
private:
 int use;//1表示被使用 0表示未使用
void* a;
ChunkNode* next;
};                                                


class BlockManager :public Node//管理块
{
public:
BlockManager(int size);//指定Chunk块的大小 num指定chunk数量
~BlockManager(){};
void setFree(int i);
int getFree();
void setBlockIndex(int i);
int getBlockIndex();
void setNext(BlockManager* b);
void setChunk(ChunkNode *cn);
void setTail(ChunkNode* tail);
ChunkNode* getTail();
void addChunk();//增加chunk
ChunkNode* getChunk();//获取头结点
ChunkNode* getChunk(int i);//获取对应节点
ChunkNode*  getFreeChunk();
BlockManager* getNext(); 
void listChunk();
private:
BlockManager* next;
ChunkNode *first;
ChunkNode *tail;
int freeNum;//空闲块数量
int blockIndex;//块序
};


//管理池
class PoolManager
{
public:
PoolManager();
~PoolManager (){};
void setBlock(BlockManager *p);//两种设置方式 一种根据大小
void setBlock(int size);
void setTail(BlockManager *p);
BlockManager* addBlock(int size);
BlockManager* getBlock();//获取块头部
BlockManager* getTail();//获取尾部
BlockManager* getBlock(int i); //获取对应块序
ChunkNode* mallocChunk(int size);//找到合适的内存chunk
ChunkNode* myMalloc(int size);
void myFree(ChunkNode* cn);//申请内存的程序在不需要内存后,通过该结构体将内存还给内存池(重载方案)
void myFree(int i, int j);//申请内存的程序在不需要内存后,通过该结构体将内存还给内存池
void freeChunk(int i, int j);//归还指定的内存
void freeChunk(ChunkNode* cn);//归还指定内存重载方法
void listBlock();//测试block遍历
int numBlock;//记录当前的block组数
CRITICAL_SECTION gSection; //关键代码段
ofstream fout;//输出日志
private:
BlockManager *bm;//头部
BlockManager *tail;//尾部
};


对应代码文件:MemoryPool.cpp

#include "MemoryManager.h"
#include <iostream>
using namespace std;
const int length = 3;
const int _size = 1000;


//基类
int Node::getSize(){
return size;
}
void Node::setSize(int c){
size = c;
}


//chunk方面
ChunkNode::ChunkNode(int n){
this->setSize(n); 
this->setUse(0);//初始化为未使用
this->setNext(NULL);
this->init();
}


void ChunkNode::setNext(ChunkNode *c){
this->next = c;
}
int ChunkNode::getUse(){
return use;
}


void ChunkNode::setUse(int u){
this->use =u;
}


//初始化chunk链表 并赋指定初值
void* ChunkNode::init(){
  this->a= (void *)malloc(this->getSize() * sizeof(void*)); 
    return a;
}


void* ChunkNode::getMem(){
return a;
}


ChunkNode* ChunkNode::getNext(){
return next;
}


//block方面
BlockManager::BlockManager(int size){
this->setNext(NULL);
this->setSize(size);
//子链处理
ChunkNode *head;
    head = new ChunkNode(size);
head->numC=0;
this->setChunk(head);
this->setFree(length);
ChunkNode *temp;
temp=head;
for (int i=1;i<length;i++)
{
ChunkNode  *p;
p = new ChunkNode(size);
p->numC=i;
temp->setNext(p);
temp=p;
}
this->setTail(temp);
}


void BlockManager::setNext(BlockManager* b){
this->next = b;
}
void BlockManager::setFree(int i){
this->freeNum = i;
}


int BlockManager::getFree(){
return freeNum;
}


void BlockManager::setBlockIndex(int i){
this->blockIndex = i;
}


int BlockManager::getBlockIndex(){
return blockIndex;
}


void BlockManager::setChunk(ChunkNode *cn){
first = cn;
}


ChunkNode* BlockManager::getChunk(){
first->numB=this->getBlockIndex();
return first;
}


ChunkNode* BlockManager::getChunk(int i){
ChunkNode* b = this->getChunk();
for (int j=1;j<i;j++)
{
b=b->getNext();
}
b->numB = this->getBlockIndex();
return b;
}


ChunkNode* BlockManager::getFreeChunk(){
ChunkNode* cn =NULL;
cn =this->getChunk();
int i=0;//记录chunk块序
int num = this->getFree();
while (cn!=NULL)
{
i++;
if(cn->getUse()==0){
cn->numC =i;
num--;
this->setFree(num);
return cn;
}
cn=cn->getNext();


if (num ==0)
{
cout<<"this block don't has free chunk";
break;
}
}
//表示未找到
cout<<"未找到合适的chunk"<<endl;
return NULL;
}


BlockManager* BlockManager::getNext(){
return next;
}




//chunk遍历
void BlockManager::listChunk(){
ChunkNode* c = this->getChunk();
while(c!=NULL){
cout<<" "<<c->getUse()<<" ";
c= c->getNext();
}
cout<<endl;
}


void BlockManager::setTail(ChunkNode* cn){
this->tail = cn;
}


ChunkNode* BlockManager::getTail(){
return this->tail;
}


void BlockManager::addChunk(){
ChunkNode* cn = new ChunkNode(this->getSize());
this->getTail()->setNext(cn);
this->setTail(cn);
int i = this->getFree();
this->setFree(++i);
}


//Pool方面
//构造函数分配块 初始化动态创建3个
PoolManager::PoolManager(){
int size = 3;
//测试输出日志
fout.open("test.txt",ios::out|ios::app);
//子链处理
BlockManager *head;
    head = new BlockManager(size);
this->numBlock =1;
    InitializeCriticalSection(&gSection);    
head->setBlockIndex(1);
this->setBlock(head);
BlockManager *temp;
temp=head;
for (int i=size*10;i<=10000;i*=10)//4个区域 10 100 1000 10000 
{
BlockManager  *p;
p = new BlockManager(_size);
++this->numBlock;
p->setBlockIndex(this->numBlock);
temp->setNext(p);
temp=p;


}
this->setTail(temp);
}


//分配块
void PoolManager::setBlock(int size){
BlockManager *b= new BlockManager(size);
bm=b;
}


void PoolManager::setBlock(BlockManager *p){
bm = p;
}


void PoolManager::setTail(BlockManager *p){
this->tail =p;
}


BlockManager* PoolManager::addBlock(int size){
  BlockManager *b= new BlockManager(size);
    this->getTail()->setNext(b);
this->setTail(b);
++this->numBlock;
  b->setBlockIndex(this->numBlock);
  return b;
}


BlockManager* PoolManager::getBlock(){
return bm;
}


BlockManager* PoolManager::getBlock(int i){
BlockManager* b = this->getBlock();
for (int j=1;j<i;j++)
{
b=b->getNext();
}
return b;
}


BlockManager* PoolManager::getTail(){
return tail;
}


ChunkNode* PoolManager::myMalloc(int size){
EnterCriticalSection(&gSection);
ChunkNode* cn = this->mallocChunk(size);
LeaveCriticalSection(&gSection);
return cn;
}


ChunkNode* PoolManager::mallocChunk(int size){ 
BlockManager* b = this->getBlock();
int j=0;
    while (b!=NULL)
         { 
if (b->getSize()==size&&b->getFree()>0)
{
//如果block大小合适且有空闲块 则分配
 ChunkNode* c =b->getFreeChunk();
 if (c==NULL)
 {
 cout<<"don't have block"<<endl;
 break;//表示没有合适的块
 }
              c->numB = b->getBlockIndex();
 c->setUse(1);
  cout<<"this id malloc "<<GetCurrentThreadId()<<": ";
            fout<<"this id malloc "<<GetCurrentThreadId()<<": ";
 cout<<"size:"<<b->getSize()<<" block("<<c->numB<<","<<c->numC<<") malloc success this block free:"<<b->getFree()<<endl;
 fout<<"size:"<<b->getSize()<<" block("<<c->numB<<","<<c->numC<<") malloc success this block free:"<<b->getFree()<<endl;
       return c;
}
j++;
b= b->getNext();
         }
//如果没找到合适大小的block则自动创建新的block
  b=this->addBlock (size);// 为其生成指定大小的size  //buildSize(size)
  ChunkNode* c =b->getFreeChunk();
  c->numB= b->getBlockIndex();
  c->setUse(1);
  cout<<"this id malloc new"<<GetCurrentThreadId()<<": ";
    fout<<"this id malloc new"<<GetCurrentThreadId()<<": ";
   cout<<"size:"<<b->getSize()<<" block("<<c->numB<<","<<c->numC<<") malloc success this block free:"<<b->getFree()<<endl;
   fout<<"size:"<<b->getSize()<<" block("<<c->numB<<","<<c->numC<<") malloc success this block free:"<<b->getFree()<<endl;
  return c;
}


void PoolManager::myFree(int i, int j){
EnterCriticalSection(&gSection);
this->freeChunk(i, j);
LeaveCriticalSection(&gSection);
}


void PoolManager::myFree(ChunkNode* cn){
EnterCriticalSection(&gSection);
this->freeChunk(cn);
LeaveCriticalSection(&gSection);
}


void PoolManager::freeChunk(int i,int j){
//将use设为0表示空闲
BlockManager* b = this->getBlock(i);
int free = b->getFree();
ChunkNode* c = b->getChunk(j);
if (c->getUse()==0)
{
cout<<"this id "<<GetCurrentThreadId()<<"error: block("<<i<<","<<j<<")has not been used"<<endl;
fout<<"this id "<<GetCurrentThreadId()<<"error: block("<<i<<","<<j<<")has not been used"<<endl;
}else if (c->getUse()==1)
{
cout<<"before free: "<<b->getFree()<<endl;
fout<<"before free: "<<b->getFree()<<endl;
free++;
b->setFree(free);
c->setUse(0);//设为未用
cout<<"this id free "<<GetCurrentThreadId()<<": ";
fout<<"this id free "<<GetCurrentThreadId()<<": ";
cout<<"succes:block("<<i<<","<<j<<")recycle"<<" this block free: "<<b->getFree()<<endl;
fout<<"succes:block("<<i<<","<<j<<")recycle"<<"  this block free: "<<b->getFree()<<endl;
}
}




void PoolManager::freeChunk(ChunkNode* cn){
if (cn->getUse() == 0){
cout << "this id " << GetCurrentThreadId() << "error: block(" << cn->numB << "," << cn->numC<< ")has not been used" << endl;
fout << "this id " << GetCurrentThreadId() << "error: block(" << cn->numB << "," << cn->numC << ")has not been used" << endl;
}
else if (cn->getUse() == 1)
{
BlockManager* b = this->getBlock(cn->numB);
int free = b->getFree();
cout << "before free: " << b->getFree() << endl;
fout << "before free: " << b->getFree() << endl;
free++;
b->setFree(free);
cn->setUse(0);//设为未用
cout << "this id free " << GetCurrentThreadId() << ": ";
fout << "this id free " << GetCurrentThreadId() << ": ";
cout << "succes:block(" << cn->numB << "," << cn->numC << ")recycle" << " this block free: " << b->getFree() << endl;
fout << "succes:block(" << cn->numB << "," << cn->numC << ")recycle" << "  this block free: " << b->getFree() << endl;
}
}


void PoolManager::listBlock(){
BlockManager* bm = this->getBlock();
while (bm!=NULL)
{
cout<<bm->getBlockIndex()<<endl;
cout<<bm->getSize()<<endl;
bm->listChunk();
bm = bm->getNext();
}
}


对应测试代码:MemoryPool.cpp

#include "MemoryManager.h"
#include <iostream>
#include <windows.h>
#include "conio.h"
using namespace std;
ChunkNode* cn = NULL, *cn1 = NULL,*cn2 = NULL;
PoolManager* p = NULL;
//线程函数  
DWORD WINAPI ThreadFun(LPVOID pM)
{
ChunkNode* cn3 = NULL;
int i = 0;
while (1)
{
cn3 = p->myMalloc(1000);
Sleep(5);
p->myFree(cn3);
i++;
}
p->listBlock();


return 0;
}


DWORD WINAPI ThreadFun2(LPVOID pM)
{
while (1)
{
cn = p->mallocChunk(1000);
Sleep(1);
p->freeChunk(cn->numB, cn->numC);
}
p->listBlock();
return 0;
}


//交叉多线程
void test1(){
HANDLE handle[10];
HANDLE handle1[5];
for (int i = 0; i < 10; i++)
{
handle[i] = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
// handle1[i] = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);  
}
//   handle1[0] = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);  
CloseHandle(handle);
CloseHandle(handle1);
}


//多线程1
void test2(){
HANDLE handle, handle1;
handle = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
handle1 = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
CloseHandle(handle);
CloseHandle(handle1);
}


//单线程下压力测试
void test3(){
ChunkNode* cn[12];
for (int i = 0; i < 12; i++){
cn[i] = p->mallocChunk(1000);
cout << cn[i] << endl;
}
for (int j = 0; j < 12; j++){
p->freeChunk(cn[j]->numB, cn[j]->numC);
cout << cn [j]<< endl;
}
}


//单线程压力测试2
void test4(){
int i = 200;
while (i != 0)
{
if (i == 1)
{
int j = 1;
}
cn = p->mallocChunk(1000);
// Sleep(500);
i--;
p->freeChunk(cn->numB, cn->numC);
}
}


//单线程压力测试4重载的新方案
void test5(){
cn = p->myMalloc(1000);
cn1 = p->myMalloc(1000);
cn2 = p->myMalloc(1000);
p->myFree(cn);
p->myFree(cn1);
p->myFree(cn2);
}


int main(int argc, char* argv[])
{
//开始测试
p = new PoolManager();
test1();
 // test3();
// test4();
// test5();
//  getch();
getchar();
return 0;
}


如果发现bug或者错误的地方欢迎与我联系。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值