C++内存池

来源:互联网 发布:淘宝联盟账户余额是0 编辑:程序博客网 时间:2024/06/04 17:46

<span style="font-size:18px;"> </span>
这几天闲来无聊,就想写一些程序模块,方便以后的调用,想来想去那就先写个内存池吧。在网上搜罗了一下,有很多资料,还有很多开源的线程池。正当时在犹豫该看开源代码还是自己写。

看到了一个通俗易懂的简介:http://www.cnblogs.com/bangerlee/archive/2011/09/01/2161437.html

想到网上有这么多资料我就不在此处罗列了:


软件结构图:


注意:在代码的实现中,可变内存放在了最后一项;

为了支持多线程操作(只支持linux平台),在代码中引入了无锁线程SCA模式,既能够保证程序的运行效率,又能够内存池能够安全运行的。

代码结构说明:

mempool.cpp 线程主体实现代码,通过指针数组和双向链表来维护内存池结构。其中可变内存大小可以动态更改。固定内存不支持动态扩张。但每个不同大小的内存池块长度,在初始化的时候可以根据需要设置不同的长度。

scalock.hpp:用于支持linux平台下的多线程。

main.cpp:测试代码。

好了废话不多说了,直接来代码简介:

  *brife:一个简单的内存池,
*1、通过预先的内存分配,来减少new和delete来提高程序的处理效率
*2、为了减少内存碎片,程序首先分配一大块内存,然后再划分成子内存片
*3、为减少难度,在程序归还的时候,并未进行内存合并
*4、为提高健壮性,可以单独申请一定数量的超过内存池预设值的大小
*5、为提高处理效率,全部采用C 来实现,C++封装
*6、支持UNIX平台下的多线程使用时需定义宏#define _LINUX_MULIT_THREAD
*7、内存池为空,返回为NULL,不阻塞

*8、该内存池不支持动态扩展
*author:zp info:zhang_int@sina.cndate:14-11-7

代码在linux平台上测试并通过:下一篇写模板线程池吧!!!

具体实现代码:

线程池头文件 mempool.h:

 

#include <malloc.h>#include <stdio.h>#include <string.h>#include <iostream>#define UNUSE_BLOCK0#define USE_BLOCK 1#define DIFF_SIZENUM 64#define _LINUX_MULIT_THREAD#ifdef _LINUX_MULIT_THREAD#include "scalock.hpp"#endiftypedef struct//内存池的相关属性{int _max_buf;//最大能够分配的内存int _maxnum_inprocess;//超过最大值后在进程中预留的块数int _size_num;//不同size 的buff种类个数,最多DIFF_SIZENUMint _mem_size[DIFF_SIZENUM][2];//存放size 和size的个数,种类最多64个[0] 是block大小 [1] 是block个数//需要从小到大的顺序排列long _totalsize;//总共分配的内存大小} MEMINFO;typedef struct block//内存节点链表封装{int size;void*memaddr;int flag;//使用还是未用的标志struct block* next;struct block* before;}BLOCK;typedef struct //pool 总结构封装{int free;int blocknum;int blocksize;BLOCK* block_addr;} MEMPOOL;class mempool{public:mempool(){}~mempool();static mempool* getinstance();static bool init(MEMINFO poolinfo);public:void test_fun(int order);long get_totalbyte();int getmempoolinfo();BLOCK* getmemnode(int size);void putmemnode(BLOCK* pblock);char* getlasterror();void mem_destroy();private:bool mempool_init(MEMINFO poolinfo);long mempooltotalsize(MEMINFO& poolinfo);//创建内存池bool create_mempool();BLOCK* create_blocklist(int blocksize, int blocknum, void* memaddr);BLOCK* get_maxnode(int size);//获取内存大小超过了配置中的大小BLOCK* get_normalnode(int size);//获取池中有匹配的大小private:static mempool* _mempool;MEMPOOL* m_mempool[64]; MEMINFO m_poolinfo;char errmsg[255];void* ptmpaddr;//内存池申请的一大块连续的内存#ifdef _LINUX_MULIT_THREADscalock _synlock;#endif};#endif
 2、mempool.cpp
<span style="white-space:pre"></span>通过指针数组和双向链表来维护内存该内存池
<pre name="code" class="cpp">#include "mempool.h"mempool* mempool::_mempool = NULL;mempool::~mempool(){//free(ptmpaddr);for (int i=0; i<m_poolinfo._size_num; i++){BLOCK* pnode = m_mempool[i]->block_addr;BLOCK* pnext;while (pnode){pnext = pnode->next;free(pnode);pnode = pnext;}}}bool mempool::init(MEMINFO poolinfo){_mempool = new mempool;return _mempool->mempool_init(poolinfo);}bool mempool::mempool_init(MEMINFO poolinfo){m_poolinfo = poolinfo;if (mempooltotalsize(m_poolinfo) == 0){return false;}return create_mempool();}mempool* mempool::getinstance(){return _mempool;}char* mempool::getlasterror(){return errmsg;}void mempool::mem_destroy(){delete _mempool;_mempool = NULL;}long mempool::get_totalbyte(){return m_poolinfo._totalsize;}void mempool::test_fun(int order){if (order == -1){for (int i=0; i<m_poolinfo._size_num; i++){std::cout<<"order:"<<i<<" size:"<<m_mempool[i]->blocksize<<" free:"<<m_mempool[i]->free<<" num:"<<m_mempool[i]->blocknum<<std::endl;BLOCK* node = m_mempool[i]->block_addr;BLOCK* before;while (node){std::cout<<node->size<<" ";before = node;node = node->next;}std::cout<<std::endl;node = before;while (node){std::cout<<node->size<<" ";node = node->before;}std::cout<<std::endl;}}else{std::cout<<"order:"<<order<<" size:"<<m_mempool[order]->blocksize<<" free:"<<m_mempool[order]->free<<" num:"<<m_mempool[order]->blocknum<<std::endl;BLOCK* node = m_mempool[order]->block_addr;BLOCK* before;while (node){std::cout<<node->size<<" ";before = node;node = node->next;}std::cout<<std::endl;node = before;while (node){std::cout<<node->size<<" ";node = node->before;}std::cout<<std::endl;}}BLOCK* mempool::getmemnode(int size){BLOCK* pmemblock;#ifdef _LINUX_MULIT_THREAD_synlock.sca_lock();#endifif (size > m_poolinfo._max_buf)//超过了最大值{pmemblock = get_maxnode(size);}else{pmemblock = get_normalnode(size);}#ifdef _LINUX_MULIT_THREAD_synlock.sca_unlock();#endifreturn pmemblock;}BLOCK* mempool::get_maxnode(int size){int searchflag = 0;//max-list 可用个数为0if (m_mempool[m_poolinfo._size_num]->free != 0){BLOCK* pnode = m_mempool[m_poolinfo._size_num]->block_addr;while (pnode){if (pnode->size>=size&&pnode->flag == UNUSE_BLOCK){pnode->flag = USE_BLOCK;searchflag = 1;return pnode;}pnode = pnode->next;}}if (searchflag == 0){if (m_mempool[m_poolinfo._size_num]->blocknum<m_poolinfo._maxnum_inprocess){BLOCK* pcur = (BLOCK*)malloc(sizeof(BLOCK));pcur->size = size;pcur->memaddr = malloc(size);pcur->flag = USE_BLOCK;pcur->next = NULL;if (NULL == m_mempool[m_poolinfo._size_num]->block_addr){pcur->before = NULL;m_mempool[m_poolinfo._size_num]->block_addr = pcur;}else{BLOCK* pnode = m_mempool[m_poolinfo._size_num]->block_addr;while (pnode->next){pnode = pnode->next;}pnode->next = pcur;pcur->before = pnode;}m_mempool[m_poolinfo._size_num]->blocknum++;m_mempool[m_poolinfo._size_num]->blocksize++;//test_fun(m_poolinfo._size_num);return pcur;}//挂载个数已经大于_maxnum_inprocess//遍历max list 删除其中一个未用的node,重新生成一个nodeBLOCK* pnode = m_mempool[m_poolinfo._size_num]->block_addr;while (pnode){/*if (m_mempool[m_poolinfo._size_num]->blocknum == 2){test_fun(m_poolinfo._size_num);}*/if (pnode->flag == UNUSE_BLOCK){BLOCK* pcur = (BLOCK*)malloc(sizeof(BLOCK));pcur->size = size;pcur->memaddr = malloc(size);pcur->flag = USE_BLOCK;BLOCK* pbefore = pnode->before;if (pbefore != NULL){pbefore->next = pcur;}else//更新头结点m_mempool[m_poolinfo._size_num]->block_addr = pcur;pcur->before = pbefore;BLOCK* pnext = pnode->next;pcur->next = pnext;if (pnext != NULL){if (pnext->before != NULL){pnext->before = pcur;}}free(pnode->memaddr);free(pnode);/*if (m_mempool[m_poolinfo._size_num]->blocknum == 2){test_fun(m_poolinfo._size_num);}*/return pcur;}pnode = pnode->next;}strcpy(errmsg, "mempool exception:max buff has been bigger than _maxnum_inprocess.");return NULL;}}BLOCK* mempool::get_normalnode(int size){int searchflag = 0;//遍历mem pool 得到合适的大小,当为free=0 return NULLfor (int i=0; i<m_poolinfo._size_num; i++){if (m_mempool[i]->blocksize>=size){if (m_mempool[i]->free != 0){m_mempool[i]->free--;BLOCK* pnode = m_mempool[i]->block_addr;while (pnode){if (pnode->flag == UNUSE_BLOCK){pnode->flag = USE_BLOCK;return pnode;}pnode = pnode->next;}}else{strcpy(errmsg, "mempool exception:no unuse_block in mempool."); return NULL;}}}}void mempool::putmemnode(BLOCK* pblock){pblock->flag = UNUSE_BLOCK;if (pblock->size > m_poolinfo._max_buf){m_mempool[m_poolinfo._size_num]->free++;return;}for (int i=0; i<m_poolinfo._size_num; i++){if (m_mempool[i]->blocksize>=pblock->size){m_mempool[i]->free++;break;}}}long mempool::mempooltotalsize(MEMINFO& poolinfo){if (poolinfo._size_num >= (DIFF_SIZENUM-1)){strcpy(errmsg, "mempool exception:mem pool diff size bigger than DIFF_SIZENUM.");return 0;}m_poolinfo = poolinfo;m_poolinfo._totalsize = 0;for (int i=0; i<m_poolinfo._size_num; i++){m_poolinfo._totalsize += (m_poolinfo._mem_size[i][0]*m_poolinfo._mem_size[i][1]);}m_poolinfo._max_buf = m_poolinfo._mem_size[m_poolinfo._size_num-1][0];return m_poolinfo._totalsize;}bool mempool::create_mempool(){bool bret = true;if (m_poolinfo._totalsize != 0){ptmpaddr = (void*)malloc(m_poolinfo._totalsize);if (ptmpaddr != NULL){for (int i=0; i<m_poolinfo._size_num; i++){m_mempool[i] = (MEMPOOL*)malloc(sizeof(MEMPOOL));m_mempool[i]->blocksize = m_poolinfo._mem_size[i][0];m_mempool[i]->blocknum = m_poolinfo._mem_size[i][1];m_mempool[i]->free = m_mempool[i]->blocknum;m_mempool[i]->block_addr = create_blocklist(m_mempool[i]->blocksize, m_mempool[i]->blocknum, ptmpaddr);ptmpaddr += m_mempool[i]->blocksize * m_mempool[i]->blocknum;}//初始化超过范围的list,并将其挂载个数设置为0m_mempool[m_poolinfo._size_num] = (MEMPOOL*)malloc(sizeof(MEMPOOL));m_mempool[m_poolinfo._size_num]->blocknum = 0;m_mempool[m_poolinfo._size_num]->block_addr = NULL;}else{bret = false;snprintf(errmsg, 255, "mempool exception: malloc mem size %d error.", m_poolinfo._totalsize);}}else{bret = false;strcpy(errmsg, "mempool exception: mem pool size = 0.");}return bret;}BLOCK* mempool::create_blocklist(int blocksize, int blocknum, void* memaddr){BLOCK* phead = NULL;BLOCK* pcur = NULL;BLOCK* pbefore = NULL;BLOCK* pnext = NULL;phead = (BLOCK*)malloc(sizeof(BLOCK));pcur = phead;pcur->before = NULL;pcur->next = NULL;for (int i=0; i<blocknum; i++){pcur->size = blocksize;pcur->flag = UNUSE_BLOCK;if (memaddr != NULL){pcur->memaddr = memaddr;}else{strcpy(errmsg, "mempool exception:create_blocklist error");break;}memaddr += blocksize;pcur->before = pbefore;if (i < (blocknum-1)){pnext = (BLOCK*)malloc(sizeof(BLOCK));pnext->before = pcur;pcur->next = pnext;pbefore = pcur;pcur = pnext;}else{pcur->next = NULL;pcur->before = pbefore;}}return phead;}
3、支持多线程的无锁同步方式

<span style="white-space:pre"></span><pre name="code" class="cpp">#ifndef __NOLOCKMODE_H#define __NOLOCKMODE_H/***********************************************************************Author:zpDate:14-8-22************************************************************************/#include <pthread.h>#include <stdio.h>#include <unistd.h>class scalock{public:scalock(){m_mutex = 0;m_lock = 1;m_unlock = 0;}~scalock(){}void sca_lock();void sca_unlock();bool sca_trylock();private:int m_mutex;int m_lock;int m_unlock;};inline void scalock::sca_lock(){while (!(__sync_bool_compare_and_swap(&m_mutex, m_unlock, m_lock))){usleep(10);}}inline bool scalock::sca_trylock(){int count = 0;while (count < 5){if (__sync_bool_compare_and_swap(&m_mutex, m_unlock, m_lock))//if true return true;count++;usleep(10);}return false;}inline void scalock::sca_unlock(){__sync_bool_compare_and_swap(&m_mutex, m_lock, m_unlock);}#endif
<span style="white-space:pre"></span>4、main函数测试
<span style="white-space:pre"></span>在线程和多线线程中测试通过。运行正常。
<pre name="code" class="cpp">#include <iostream>#include "mempool.h"#include <pthread.h>#include <unistd.h>bool check_fun(BLOCK* block){bool bret = true;if (block == NULL){bret = false;std::cout<<mempool::getinstance()->getlasterror()<<std::endl;}else{std::cout<<"block size:"<<block->size<<std::endl;}return bret;}void* thread_run(void* arg){int num = 0;int size = 10;while (num<100){BLOCK* pblock = mempool::getinstance()->getmemnode(size);if (pblock == NULL){ std::cout<<mempool::getinstance()->getlasterror()<<std::endl;}else{snprintf((char*)pblock->memaddr, pblock->size, "test data- num:%d size:%d.", num, size);std::cout<<"threadid:"<<pthread_self()<<" "<<(char*)pblock->memaddr<<std::endl;mempool::getinstance()->putmemnode(pblock);}num++;size = size+10;usleep(10*1000);}}int main(void){MEMINFO _loopstate;_loopstate._size_num = 3;_loopstate._mem_size[0][0] = 70;_loopstate._mem_size[0][1] = 100;_loopstate._mem_size[1][0] = 100;_loopstate._mem_size[1][1] = 100;_loopstate._mem_size[2][0] = 200;_loopstate._mem_size[2][1] = 100;_loopstate._maxnum_inprocess = 2;mempool::init(_loopstate);std::cout<<"mem pool size:"<<mempool::getinstance()->get_totalbyte()<<std::endl;mempool::getinstance()->test_fun(-1);//单线程测试实例BLOCK* tmp1 = mempool::getinstance()->getmemnode(20);BLOCK* tmp2 = mempool::getinstance()->getmemnode(20);BLOCK* tmp3 = mempool::getinstance()->getmemnode(100);BLOCK* tmp4 = mempool::getinstance()->getmemnode(100);check_fun(tmp1);check_fun(tmp2);check_fun(tmp3);check_fun(tmp4);char*val1 = (char*)tmp1->memaddr;char*val2 = (char*)tmp2->memaddr;char*val3 = (char*)tmp3->memaddr;char*val4 = (char*)tmp4->memaddr;char testchar_1[] = "0123456789012345678";char testchar_2[] = "9876543210987654321";memcpy(val1, testchar_1, strlen(testchar_1));memcpy(val2, testchar_2, strlen(testchar_2));memcpy(val3, testchar_1, strlen(testchar_1));memcpy(val4, testchar_2, strlen(testchar_2));std::cout<<"val1:"<<val1<<std::endl;std::cout<<"val2:"<<val2<<std::endl;std::cout<<"val3:"<<val3<<std::endl;std::cout<<"val4:"<<val4<<std::endl;//多线程测试int threadnum = 10;pthread_t thrdid[64];for (int i=0; i<threadnum; i++){pthread_create(&thrdid[i], NULL, thread_run, NULL);}for (int i=0; i<threadnum; i++){pthread_join(thrdid[i], NULL);}mempool::getinstance()->mem_destroy();return 0;}







0 0
原创粉丝点击