一种固定内存池的实现(含代码)
来源:互联网 发布:rt809f编程器优缺点 编辑:程序博客网 时间:2024/06/05 11:11
转载:http://blog.csdn.net/hairetz/article/details/4538578
所谓内存池,是指,应用程序可以通过系统的内存分配调用预先一次性申请适当大小的内存作为一个内存池,之后应用程序自己对内存的分配和释放则可以通过这个内存池来完成。只有当内存池大小需要动态扩展时,才需要再调用系统的内存分配函数,其他时间对内存的一切操作都在应用程序的掌控之中。
应用程序自定义的内存池根据不同的适用场景又有不同的类型。
从线程安全的角度来分,内存池可以分为单线程内存池和多线程内存池。单线程内存池整个生命周期只被一个线程使用,因而不需要考虑互斥访问的问题;多线程内存池有可能被多个线程共享,因此则需要在每次分配和释放内存时加锁。相对而言,单线程内存池性能更高,而多线程内存池适用范围更广。
从内存池可分配内存单元大小来分,可以分为固定内存池和可变内存池。所谓固定内存池是指应用程序每次从内存池中分配出来的内存单元大小事先已经确定,是固定不变的;而可变内存池则每次分配的内存单元大小可以按需变化,应用范围更广,而性能比固定内存池要低。
具体的介绍可见IBM这篇文章:
http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html?ca=drs-cn
前段时间有空余,就写了段基本的内存池实现,暂不支持多线程,且是固定内存池。
大家想参考这片文章来实现的,可以看看我这里的代码。
ps:很感谢小赖帮我调试出了内存回收的bug,有的时候写一段代码只要1,2小时,但是找bug可能真的得1天。
memory_pool.h
#ifndef MEMORY_POOL_H#define MEMORY_POOL_H/************************************ author:hairetzhang ** date:2009.9.1 ** funtion: regular memory pool lib ** version 1.0 ** *************************************/#include <iostream>#include <malloc.h>using namespace std;#define USHORT unsigned short#define ULONG unsigned long#define ADATAUNIT 2#define MEMPOOL_ALIGNMENT 4 //机器的字节对齐数struct MemoryBlock{MemoryBlock* pNext;USHORT nSize; //每个block的总小块数 USHORT nfree_left; //剩余小块的数目 USHORT nfirst_index; //第一个可用小块的索引号 USHORT aData[1]; //第一个小块前一个字节,不被使用//nSize = nTypes; //记录分配的小块数//pNext = NULL;static void* block_new( USHORT nTypes, USHORT nUnitSize){MemoryBlock* my_block;my_block = (MemoryBlock *) malloc(sizeof(MemoryBlock) + nTypes * nUnitSize);cout << "sizeof block is :" << sizeof(MemoryBlock) <<endl;my_block->nSize = nTypes; //申请时,块内初始化my_block->nfree_left = nTypes;my_block->nfirst_index = 0;my_block->pNext = NULL;return my_block;}static void block_delete(void *p ){free(p);}MemoryBlock (USHORT nTypes = 1, USHORT nUnitSize = 0);~MemoryBlock();};class MemoryPool{private: MemoryBlock* pBlock; USHORT nUnitSize; USHORT nInitSize; USHORT nGrowSize;public: MemoryPool( USHORT nUnitSize, USHORT nInitSize = 1024, USHORT nGrowSize = 256 ); ~MemoryPool(); void* Alloc(); void Free( void* p ); void init_block(MemoryBlock* new_block , USHORT nSize);void* get_pblock(); //用于调试};#endif
memory_pool.cpp
#include "stdafx.h"#include <iostream>#include <stdio.h>#include "memory_pool.h"using namespace std;MemoryPool::MemoryPool( USHORT _nUnitSize, USHORT _nInitSize, USHORT _nGrowSize ){ pBlock = NULL; nInitSize = _nInitSize; //每个块分配的索引小块数 nGrowSize = _nGrowSize; //增长块的内存索引小块数 //设置小块的大小 if ( _nUnitSize > 4 ) nUnitSize = (_nUnitSize + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1); else if ( _nUnitSize <= 2 ) nUnitSize = 2; else nUnitSize = 4;}void MemoryPool::init_block( MemoryBlock* new_block ,USHORT nSize ) //初始化分配的新块,nSize为该块的总索引数{char *pdata = (char * )new_block->aData; //从第二个小块开始设置索引,第一个小块返回提供使用USHORT *mini_block_head;for(int i = 1 ;i < nSize; ++i) //设置每个小块的索引头,0号返回给该次申请者使用{mini_block_head = (USHORT *)(pdata+nUnitSize*i +ADATAUNIT);*mini_block_head = i+1;}new_block->nfirst_index = 1;new_block->nfree_left = nSize-1;}void* MemoryPool::Alloc(){if( !pBlock ) //当前内存池尚无内存块,第一次分配{pBlock = (MemoryBlock *) MemoryBlock::block_new (nInitSize, nUnitSize);init_block( pBlock ,nInitSize);return (void *) (pBlock->aData+1);}MemoryBlock* pMyBlock = pBlock; //从链表头部pBlock开始 while (pMyBlock && !pMyBlock->nfree_left ) //搜索可用内存快 pMyBlock = pMyBlock->pNext;if ( pMyBlock ) //尚有可用的内存快 { char* pFree = (char *) ( (ULONG)pMyBlock->aData+( pMyBlock->nfirst_index*nUnitSize)+ADATAUNIT );printf("pMyBlock->aData:%p, pFree:%p/n",pMyBlock->aData,pFree);pMyBlock->nfirst_index = *( (USHORT *)pFree ); //每小块的头部两字节记录了下一个可用索引号 pMyBlock->nfree_left--; return (void*)pFree; }else //找不到可用内存块 { if ( !nGrowSize ) return NULL; pMyBlock = (MemoryBlock *)MemoryBlock::block_new (nGrowSize, nUnitSize); if ( !pMyBlock ) return NULL;pMyBlock->pNext = pBlock; //新块插入到块链表头部 pBlock = pMyBlock;init_block( pMyBlock ,nGrowSize); return (void*)(pMyBlock->aData+ADATAUNIT); }}void MemoryPool::Free( void* pFree ){ USHORT* pfree_us; USHORT pfree_index, pHead;pfree_us = (USHORT *)pFree; MemoryBlock* pMyBlock = pBlock;MemoryBlock* pre_pBlock = NULL; while ( ((ULONG)pMyBlock->aData > (ULONG)pfree_us) || ((ULONG)pfree_us >= ((ULONG)pMyBlock->aData + pMyBlock->nSize*nUnitSize)) ) //定位pFree所在的块 { pre_pBlock = pMyBlock; pMyBlock = pMyBlock->pNext; }if(pMyBlock == NULL) //pFree不是属于内存池管理的内存return;//回收pFreepMyBlock->nfree_left++; pHead = pMyBlock->nfirst_index; //第一个可用索引 pfree_index = ( (ULONG)pfree_us-(ULONG)pMyBlock->aData -ADATAUNIT)/nUnitSize; //获取pFree的索引号pMyBlock->nfirst_index = pfree_index; //pFree插入到可用块首*pfree_us = pHead; //之前的块首链入 //判断是否需要将Block内存返回给系统 if (pMyBlock->nfree_left == pMyBlock->nSize ) {if(pre_pBlock) //删除的不是第一个MemoryBlockpre_pBlock->pNext = pMyBlock->pNext;pBlock = pMyBlock->pNext; //删除的是第一个MemoryBlockMemoryBlock::block_delete(pMyBlock); }}MemoryPool::~MemoryPool() //析构函数释放所有的MemoryBlock,即使用户忘记free掉自己申请的内存也不会发生内存泄漏{MemoryBlock* my_block = pBlock;MemoryBlock* next_block = NULL;while( my_block ){next_block = my_block->pNext;MemoryBlock::block_delete( (void *)my_block);my_block = next_block;}}void* MemoryPool::get_pblock(){return pBlock;}
- 一种固定内存池的实现(含代码)
- 一种固定内存池的实现(含代码)
- 一种固定内存池的实现(含代码)
- 一种固定内存池的实现(C++)
- 内存池的一种实现
- 内存池的一种简单的实现
- 一种高效的 C++ 固定内存块分配器
- 固定的,高效的内存池实现机器应用
- 一个简单的固定长度内存池的实现
- 单线程固定大小对象的内存池实现
- 单线程不固定大小对象的内存池实现
- 简单实现一个固定大小的内存池
- 固定长度的内存池
- [html][jQuery]表头固定在顶部的一种实现思路
- 最简单的一种栈 固定大小 [数组实现]
- 固定块内存池c语言实现
- 固定大小内存池设计与实现
- 基于策略的一种高效内存池的实现
- java笔记总结_06_集合泛型
- Web导出(一)之HTML代码导出到Word
- 如何提高微博粉丝数
- 网站后台管理系统需求分析与详细设计代码 【命令行界面】
- 瞎混了好久,今天开博
- 一种固定内存池的实现(含代码)
- 做对决策
- 一些防止java代码被反编译的方法
- 迷宫求解
- 进程通信/线程同步方式总结
- wampserver2.0配置本机项目
- linux消息队列
- iptables限速的办法
- Lucene学习