您的位置:首页 > 其它

内存池的一种实现

2012-05-30 13:52 274 查看
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <semaphore.h>

#include "Const.h"

#include "UtilityFunc.h"

#include "hashtable.h"

#include "logmsg.h"

#define SYSTEM_PAGE_SIZE 4096

#define DEFAULT_MAX_NUM 128

typedef enum EnumMemPoolOper // 对内存池的4种操作

{

MEMPOOL_MAX_NUM = 0, // 内存池总数

MEMPOOL_CURR_USED = 1, // 当前使用数

MEMPOOL_GET_SUCC = 2, // Get成功

MEMPOOL_GET1_FAIL = 3, // Get失败

MEMPOOL_GET2_FAIL = 4, // Get失败

MEMPOOL_PUT_SUCC = 5, // Put成功

MEMPOOL_PUT_NULL = 6, // Put失败

MEMPOOL_PUT1_FAIL = 7, // Put失败

MEMPOOL_PUT2_FAIL = 8, // Put失败

MEMPOOL_TOTAL_SIZE = 9, // 内存池的字节大小

MEMPOOL_DATA_SIZE = 10, // 每个池子的数据大小

MEMPOOL_POOL_COUNT = 11, // 池子个数

MEMPOOL_OPER_COUNT = 12 // 仅为计数

}EnumMemPoolOper;

extern bool g_bCollectorStarted;

template <class T>

class MemPoolCls

{

public:

MemPoolCls();

~MemPoolCls();

void enableDebug();

void setMaxNum(int maxNum, bool bPreAlloc=false);

// int getMaxNum() { return m_intMaxNum; };

// int getUsedNum() { return m_currPos; };

// int getSize() { return m_intMaxNum*sizeof(T); };

T* getMem();

bool recycleMem(T* pClsMem);

// void printAll();

unsigned long getRecycleFailedNum() { return (m_ulMemAccess[MEMPOOL_PUT1_FAIL] + m_ulMemAccess[MEMPOOL_PUT2_FAIL]); };

unsigned long* getMemAccess() { return m_ulMemAccess; };

protected:

void initMemPool();

T** m_ppMemPool;

int m_intMaxNum;

int m_currPos;

int m_intRecNum;

//sem_t m_semMemPool;

pthread_mutex_t m_mutex;

bool m_bPreAlloc;

bool m_bLogGet1Fail;

bool m_bLogPut1Fail;

unsigned long m_ulMemAccess[MEMPOOL_OPER_COUNT];

// 调试信息

bool DEBUG_MEMPOOL;

HashTableCls *m_mapAllPtr; // 存储所有指针

unsigned char *m_pUsedFlag;

};

template<class T>

MemPoolCls<T>::~MemPoolCls()

{

if(m_ppMemPool)

{

if( m_bPreAlloc )

{

if(m_ppMemPool[0])

free(m_ppMemPool[0]);

}

else

{

for(int i = 0 ; i < m_intMaxNum ; i++)

{

delete m_ppMemPool[i];

}

}

free(m_ppMemPool);

}

}

template<class T>

MemPoolCls<T>::MemPoolCls()

{

m_intMaxNum = DEFAULT_MAX_NUM;

//sem_init(&m_semMemPool, 0, 1);

pthread_mutex_init (&m_mutex, NULL);

m_ppMemPool = NULL;

m_currPos = 0;

m_intRecNum = 0;

DEBUG_MEMPOOL = false;

m_mapAllPtr = NULL;

m_pUsedFlag = NULL;

m_bPreAlloc = false;

m_bLogGet1Fail = false;

m_bLogPut1Fail = false;

bzero(m_ulMemAccess, sizeof(m_ulMemAccess));

m_ulMemAccess[MEMPOOL_DATA_SIZE] = sizeof(T);

}

template<class T>

void MemPoolCls<T>::enableDebug()

{

DEBUG_MEMPOOL = true;

m_mapAllPtr = new HashTableCls(1024000);

}

template<class T>

void MemPoolCls<T>::setMaxNum(int maxNum, bool bPreAlloc)

{

//sem_wait(&m_semMemPool);

pthread_mutex_lock (&m_mutex);

m_intMaxNum = maxNum;

m_ulMemAccess[MEMPOOL_MAX_NUM] = maxNum;

m_ulMemAccess[MEMPOOL_TOTAL_SIZE] = m_intMaxNum * sizeof(T);

//m_bPreAlloc = true;

m_bPreAlloc = bPreAlloc;

//sem_post(&m_semMemPool);

pthread_mutex_unlock (&m_mutex);

if(!m_ppMemPool)

initMemPool();

}

template<class T>

void MemPoolCls<T>::initMemPool()

{

//sem_wait(&m_semMemPool);

pthread_mutex_lock (&m_mutex);

m_ppMemPool = (T**)calloc(sizeof(T*),m_intMaxNum);

char strInfo[100] = "";

// 2011-02-18 理论上不应该出现

if ( g_bCollectorStarted )

{

snprintf(strInfo, 100, "initMemPool %u\n", m_intMaxNum);

LOG(LOGTYPE_ERROR, strInfo);

}

m_ulMemAccess[MEMPOOL_TOTAL_SIZE] = m_intMaxNum * sizeof(T);

pair<ITERTYPE_IP, bool> rslt;

///////////////////////////////////////////////////////////////////////////

// for heap memory alloc test.

//

if( m_bPreAlloc )

{

T* pStartBuffer = NULL;

//calculate the total bytes and round it to multiple of system page size.

unsigned long MemSize = m_intMaxNum * sizeof(T);

MemSize = MemSize / SYSTEM_PAGE_SIZE * SYSTEM_PAGE_SIZE + SYSTEM_PAGE_SIZE;

try

{

pStartBuffer = (T*)malloc(MemSize);//PAGE_NOACCESS);

if( pStartBuffer == NULL )

{

printf("VM alloc failed!\n");

exit(-1);

}

}

catch( ... )

{

//STATUS_NO_MEMORY

//STATUS_ACCESS_VIOLATION

for(int i = 0 ; i < m_intMaxNum ; i++)

{

m_ppMemPool[i] = NULL;

}

m_currPos = 0;

m_intRecNum = 0;

//e->Delete();

printf( " Sys mem alloc fail! exiting ... " );

getchar();

exit(-1);

//return;

}

for(int i = 0 ; i < m_intMaxNum ; i++)

{

m_ppMemPool[i] = pStartBuffer;

// if ( DEBUG_MEMPOOL )

// {

// rslt = m_mapAllPtr.insert( VT_IP((unsigned long)pStartBuffer, NULL) );

// if ( !rslt.second )

// {

// ;

// }

// }

++pStartBuffer;

//test to see if we've got want we want.

try

{

memset(m_ppMemPool[i], 0, sizeof(T));

}

catch(...)

{

printf("Init mem failed! Please lower mem allocated.\n");

exit(-1);

}

}

m_currPos = 0;

m_intRecNum = 0;

// // dyn

// int m, n;

// for(m = 0 ; m < m_intMaxNum-1 ; m++)

// for(n = m+1 ; n < m_intMaxNum ; n++)

// if( m_ppMemPool[m] == m_ppMemPool
)

// printf( "Init Mem Dup! %d %d\n", m, n );

//sem_post(&m_semMemPool);

pthread_mutex_unlock (&m_mutex);

return;

}

///////////////////////////////////////////////////////////////////////////

void *pTemp = NULL;

int nTemp = 0;

for(int i = 0 ; i < m_intMaxNum ; i++)

{

m_ppMemPool[i] = new T;

bzero(m_ppMemPool[i], sizeof(T));

// 2011-02-21 记录地址和i的对应关系, [0]空出来

if ( DEBUG_MEMPOOL )

{

nTemp = i+1;

pTemp = m_mapAllPtr->insertItem( (UCHAR*)(&m_ppMemPool[i]), 4, (void*)nTemp );

if ( NULL == pTemp )

{

snprintf(strInfo, 100, "mempool insertitem fail : 0x%X-%u-%u\n", m_ppMemPool[i], m_intMaxNum, nTemp);

LOG(LOGTYPE_ERROR, strInfo);

exit(-1); // for debug

}

// 记录所有的指针

sprintf(strInfo, "%d, 0x%X\n", nTemp, m_ppMemPool[i]);

LOG(LOGTYPE_ERROR, strInfo);

}

}

// 2011-02-21 生成i的bitmap,表示是否被分配出去

if ( DEBUG_MEMPOOL )

{

int nTemp = 0;

if ( 0 == (m_intMaxNum % 8) )

{

nTemp = m_intMaxNum / 8 + 1;

m_pUsedFlag = new unsigned char[nTemp];

}

else

{

nTemp = m_intMaxNum / 8 + 2;

m_pUsedFlag = new unsigned char[nTemp];

}

bzero(m_pUsedFlag, nTemp);

}

m_currPos = 0;

m_intRecNum = 0;

//sem_post(&m_semMemPool);

pthread_mutex_unlock (&m_mutex);

}

template<class T>

T* MemPoolCls<T>::getMem()

{

if(!m_ppMemPool)

initMemPool();

//sem_wait(&m_semMemPool);

pthread_mutex_lock (&m_mutex);

char strInfo[200] = "";

unsigned long nOrg = 0;

unsigned char ucTemp = 0;

unsigned char ucMask = 0;

int nByte = 0;

int nBit = 0;

// // dyn

// int m, n;

// for(m = m_currPos ; m < m_intMaxNum-1 ; m++)

// for(n = m+1 ; n < m_intMaxNum ; n++)

// if( m_ppMemPool[m] == m_ppMemPool
)

// printf( "Get Mem Dup! %d %d\n", m, n );

T *pTemp = NULL;

if(m_currPos < m_intMaxNum)

{

pTemp = m_ppMemPool[m_currPos];

// 2011-01-15 ???? 为什么会出现这种请况?

if ( NULL == pTemp )

{

if ( !m_bLogGet1Fail )

{

m_bLogGet1Fail = true;

snprintf(strInfo, 100, "mempool get null : %u--%u(0x%X)\n", m_intMaxNum, m_currPos, m_ppMemPool[m_currPos]);

LOG(LOGTYPE_ERROR, strInfo);

//appendDebugInfo(0, strInfo);

// 输出所有内存池地址

// printAll();

}

m_ulMemAccess[MEMPOOL_GET1_FAIL]++;

goto FUNCTION_EXIT;

}

//bzero(pTemp, sizeof(T));

// 确保不被别人使用

if ( DEBUG_MEMPOOL )

{

nOrg = (unsigned long)m_mapAllPtr->lookupItem( (UCHAR*)&pTemp, 4 );

if ( 0 == nOrg )

{

snprintf(strInfo, 100, "mempool get fail: %u, %u, 0x%X\n", m_intMaxNum, m_currPos, m_ppMemPool[m_currPos]);

//LOG(LOGTYPE_ERROR, strInfo);

appendDebugInfo(0, strInfo);

m_ulMemAccess[MEMPOOL_GET1_FAIL]++;

pTemp = NULL;

goto FUNCTION_EXIT;

}

nByte = nOrg / 8 + 1;

nBit = nOrg % 8;

ucTemp = *(m_pUsedFlag + nByte);

ucMask = (ucTemp >> nBit) & 0x01;

if ( 0 == ucMask )

{

// 标志已经被分配出去了

*(m_pUsedFlag + nByte) |= (1<<nBit);

}

else

{

snprintf(strInfo, 100, "mempool reused : %u, %u, %u(%d,%d,%d), 0x%X\n",

m_currPos, nOrg, ucTemp, nByte, nBit, ucMask, m_ppMemPool[m_currPos]);

//LOG(LOGTYPE_ERROR, strInfo);

appendDebugInfo(0, strInfo);

// 死循环用于调试

printf("getMem endless loop\n");

while(1)

{

sleep(10);

}

m_ulMemAccess[MEMPOOL_GET1_FAIL]++;

pTemp = NULL;

goto FUNCTION_EXIT;

}

}

if ( DEBUG_MEMPOOL )

{

ucTemp = *(m_pUsedFlag + nByte); // 新的标志

ucMask = (ucTemp >> nBit) & 0x01;

sprintf(strInfo, "get mem : %u, %u, %u(%d,%d,%d), 0x%X\n",

m_currPos, nOrg, ucTemp, nByte, nBit,ucMask, m_ppMemPool[m_currPos]);

appendDebugInfo(0, strInfo);

}

m_ppMemPool[m_currPos] = NULL;

m_currPos = m_currPos + 1;

m_ulMemAccess[MEMPOOL_GET_SUCC]++;

m_ulMemAccess[MEMPOOL_CURR_USED] = m_currPos;

}

else

{

m_ulMemAccess[MEMPOOL_GET2_FAIL]++;

}

FUNCTION_EXIT:

if ( NULL == pTemp )

{

if( !m_bPreAlloc )

{

//printf("f");

//pTemp = new T; 2005/6/20 Never allocate! WangWei.

}

}

//sem_post(&m_semMemPool);

pthread_mutex_unlock (&m_mutex);

return pTemp;

}

template<class T>

bool MemPoolCls<T>::recycleMem(T* pClsMem)

{

//sem_wait(&m_semMemPool);

pthread_mutex_lock (&m_mutex);

bool bRet = false; // 方便在 MemFactoryCls中进行调试, 因为 .h 不好断点

char strInfo[200];

unsigned long ulTemp = (unsigned long)pClsMem;

unsigned long nOrg = 0;

unsigned char ucTemp = 0;

unsigned char ucMask = 0;

int nByte = 0;

int nBit = 0;

if ( NULL == pClsMem )

{

m_ulMemAccess[MEMPOOL_PUT_NULL]++;

bRet = false;

goto FUNCTION_EXIT;

}

// 确保是已经分配出去的

if ( DEBUG_MEMPOOL )

{

nOrg = (unsigned long)m_mapAllPtr->lookupItem( (UCHAR*)&ulTemp, sizeof(long) );

if ( 0 == nOrg )

{

snprintf(strInfo, 100, "mempool del fail: %u, %u, 0x%X\n", m_intMaxNum, m_currPos, nOrg);

//LOG(LOGTYPE_ERROR, strInfo);

appendDebugInfo(0, strInfo);

m_ulMemAccess[MEMPOOL_PUT1_FAIL]++;

goto FUNCTION_EXIT;

}

nByte = nOrg / 8 + 1;

nBit = nOrg % 8;

ucTemp = *(m_pUsedFlag + nByte);

ucMask = (ucTemp >> nBit) & 0x01;

if ( 1 == ucMask )

{

// 标志未被使用

*(m_pUsedFlag + nByte) &= ~(1<<nBit);

}

else

{

snprintf(strInfo, 100, "mempool recycle notused: %u, %u, %u(%d,%d,%d), 0x%X\n",

m_currPos, nOrg, ucTemp, nByte, nBit, ucMask, ulTemp);

//LOG(LOGTYPE_ERROR, strInfo);

appendDebugInfo(0, strInfo);

// 死循环用于调试

while(1)

{

printf("recycleMem endless loop\n");

sleep(10);

}

m_ulMemAccess[MEMPOOL_PUT1_FAIL]++;

goto FUNCTION_EXIT;

}

}

// // dyn

// int m;

// for(m = 0 ; m < m_intMaxNum ; m++)

// if( m_ppMemPool[m] != NULL && m_ppMemPool[m] == pClsMem)

// printf( "Recycle Mem Dup! %d\n", m );

if(m_currPos != 0 )

{

if ( NULL == m_ppMemPool[m_currPos-1] )

{

bRet = true;

}

else

{

if ( !m_bLogPut1Fail )

{

m_bLogPut1Fail = true;

sprintf(strInfo, "mempool recycle fail: %u, %u, 0x%X -- %u(0x%X)\n", m_currPos, nOrg, pClsMem, m_currPos-1, m_ppMemPool[m_currPos-1]);

LOG(LOGTYPE_ERROR, strInfo);

//appendDebugInfo(0, strInfo);

// 输出所有内存池地址

// printAll();

}

m_ulMemAccess[MEMPOOL_PUT1_FAIL]++;

bRet = false;

}

}

else

{

sprintf(strInfo, "mempool recycle error: %d, %d, 0x%X\n", m_currPos, nOrg, pClsMem);

LOG(LOGTYPE_ERROR, strInfo);

//appendDebugInfo(0, strInfo);

m_ulMemAccess[MEMPOOL_PUT2_FAIL]++;

bRet = false;

//if( !m_bPreAlloc )

//delete pClsMem; 2005/6/20 Never allocate! WangWei.

}

if ( bRet )

{

m_currPos = m_currPos - 1 ;

m_ppMemPool[m_currPos] = pClsMem;

m_ulMemAccess[MEMPOOL_PUT_SUCC]++;

m_ulMemAccess[MEMPOOL_CURR_USED] = m_currPos;

if ( DEBUG_MEMPOOL )

{

ucTemp = *(m_pUsedFlag + nByte);

ucMask = (ucTemp >> nBit) & 0x01;

sprintf(strInfo, "delete mem : %u, %u, %u(%d,%d,%d), 0x%X\n",

m_currPos, nOrg, ucTemp, nByte, nBit, ucMask, pClsMem);

appendDebugInfo(0, strInfo);

}

bzero(pClsMem, sizeof(T));

}

FUNCTION_EXIT:

//sem_post(&m_semMemPool);

pthread_mutex_unlock (&m_mutex);

return bRet;

}

//template<class T>

//void MemPoolCls<T>::printAll()

//{

// // 输出所有内存池地址

// int m = 0;

// int k = 0;

// char strTemp[300] = {0};

//

// for ( m = 0; m < m_intMaxNum; m++ )

// {

// if ( 0 == (m+1)%10 )

// {

// strTemp[0] = 0;

// k = 0;

// }

// k += sprintf(strTemp + k, "%8X ", m_ppMemPool[m]);

//

// if ( 0 == (m+1)%10 )

// {

// strcat(strTemp, "\n");

// LOG(LOGTYPE_ERROR, strTemp);

// }

// }

//}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: