- UID
- 31191
注册时间2007-5-1
阅读权限20
最后登录1970-1-1
以武会友
TA的每日心情 | 开心 2024-6-9 16:20 |
---|
签到天数: 24 天 [LV.4]偶尔看看III
|
关键字 对象池
原作者姓名 易剑
介绍
本篇幅主要由四大部分组成,每个部分均为一独立文件,这四部分构成了对象池的完整实现:
ObjectPool.h:定义对象池接口
ObjectPool.cpp:实现对象池
x.cpp:用来测试对象池
Makefile:用来在GnuMake上编译
由于代码比较简单,以及时间上的问题,注释不多,请多多谅解!
正文
// Filename: ObjectPool.h
// Writed by yijian on 2005-06-03
// Defines the interface of object pool
#ifndef __OBJECT_POOL_H
#define __OBJECT_POOL_H
// 声明对象池宏,该宏只能放在类的定义中,具体请参见x.cpp中的示例
#define OBJECT_POOL_DECLARE() \
private: \
static CObjectPool m_ObjPool; \
public: \
static int init(unsigned int nObjCount); \
static void fini(); \
void* operator new(unsigned int); \
void operator delete(void* p);
// 对象池实现宏,具体请参见x.cpp中的示例
#define OBJECT_POOL_IMPLEMENT(ClassName) \
CObjectPool ClassName::m_ObjPool; \
int ClassName::init(unsigned int nObjCount) \
{ \
m_ObjPool.init(sizeof(ClassName), nObjCount); \
} \
void ClassName::fini() \
{ \
m_ObjPool.fini(); \
} \
void* ClassName::operator new(unsigned int) \
{ \
return m_ObjPool.alloc(); \
} \
void ClassName::operator delete(void* p) \
{ \
m_ObjPool.free(p); \
}
// 定义对象池类
class CObjectPool
{
public:
CObjectPool();
// 用来初始化对象池,成功返回0,否则返回大于0的值
// nObjSize:对象池中一个对象的字节数
// nObjCount:对象池中可容纳的最大对象个数
int init(unsigned int nObjSize, unsigned int nObjCount);
// 用来释放初始化对象池时分配的资源
void fini();
// 从对象池中分配一个对象大小的内存块
void* alloc();
// 将一个对象大小的内存块回收到对象池中
void free(void* p);
private:
unsigned int m_nObjSize; // 对象池中对象的大小
unsigned int m_nObjCount; // 对象池中对象的最大个数
unsigned char* m_pPoolHeader; // 对象池的内存首地址
unsigned int* m_pBucket; // 保存对象地址的数组
unsigned char* m_pBucketState; // 对象状态,用来指示指定的对象内存块状态(已经分配或未分配)
int m_nStackTop; // 可用对象的位置
};
#endif // __OBJECT_POOL_H
// Filename: ObjectPool.cpp
// Writed by yijian on 2005-06-03
// Implements the object pool
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ObjectPool.h"
CObjectPool::CObjectPool()
:m_nObjSize(0),
m_nObjCount(0),
m_nStackTop(-1),
m_pPoolHeader(NULL),
m_pBucket(NULL),
m_pBucketState(NULL)
{
}
int CObjectPool::init(unsigned int nObjSize, unsigned int nObjCount)
{
m_nObjSize = nObjSize;
m_nObjCount = nObjCount;
// 入口参数检查
if (nObjSize < 1) return 1;
if (nObjCount < 1) return 2;
// 分配内存池
m_pPoolHeader = new unsigned char[nObjSize * nObjCount + 1];
memset(m_pPoolHeader, 0, nObjSize * nObjCount + 1);
// 分配保存对象地址的数组
try
{
m_pBucket = new unsigned int[nObjCount];
}
catch (...)
{
delete []m_pPoolHeader;
return 3;
}
// 分配状态数组
try
{
m_pBucketState = new unsigned char[nObjCount];
memset(m_pBucketState, 0, nObjCount);
}
catch (...)
{
delete []m_pBucket;
delete []m_pPoolHeader;
return 4;
}
// 初始化栈顶位置
m_nStackTop = nObjCount-1;
// 循环存入每一个可用对象的地址到栈中
for (unsigned int i=0; i<nObjCount; i++)
{
m_pBucket = (unsigned int)(m_pPoolHeader + (i * nObjSize));
}
return 0;
}
void CObjectPool::fini()
{
delete []m_pBucketState;
m_pBucketState = 0;
delete []m_pBucket;
m_pBucket = 0;
delete []m_pPoolHeader;
m_pPoolHeader = 0;
}
void* CObjectPool::alloc()
{
if (-1 == m_nStackTop) // Not enough now, than alloc from heap.
{
unsigned char* ptr = new unsigned char[m_nObjSize];
fprintf(stderr, "alloc from heap: %p.\n", ptr);
return ptr;
}
// 从队尾拿一个空间的对象块(bucket)
unsigned char* ptr = (unsigned char *)m_pBucket[m_nStackTop--];
unsigned int idx = (ptr - m_pPoolHeader) / m_nObjSize;
m_pBucketState[idx] = 1;
return ptr;
}
void CObjectPool::free(void* p)
{
unsigned char* ptr = (unsigned char *)p;
// 先判断释放的是否为内存池中的
if ( (ptr < m_pPoolHeader) || (ptr > m_pPoolHeader+m_nObjSize * m_nObjCount) )
{
delete []ptr;
fprintf(stderr, "*free from heap: %p.\n", ptr);
}
else
{
// 即使ptr在对象池的范围内,也不一定就是对的,这里做一下判断
if ((ptr - m_pPoolHeader) % m_nObjSize != 0)
{
fprintf(stderr, "free %p error.", ptr);
return;
}
// 回收到队尾
int idx = (ptr - m_pPoolHeader) / m_nObjSize;
if (1 == m_pBucketState[idx]) // 回收之前先判断一下是否已经回收
{
m_pBucket[++m_nStackTop] = (unsigned int)ptr;
m_pBucketState[idx] = 0;
}
}
}
// 下面是测试代码,主要是做性能测试
// Filename: x.cpp
// Writed by yijian on 2005-06-03
// This file is used to test CObjectPool performance
#include <time.h>
#include <stdio.h>
#include "ObjectPool.h"
class A
{
private:
int array[100];
};
class B
{
OBJECT_POOL_DECLARE(); // 声明对象池
private:
int array[100];
};
OBJECT_POOL_IMPLEMENT(B);
int main()
{
time_t begin1, end1;
time_t begin2, end2;
const unsigned int nPoolSize = 5000001;
const unsigned int nArraySize = 10;
const unsigned int nLoopCount = 500000;
B::init(nPoolSize);
begin2 = time(0);
for (unsigned int i=0; i<nLoopCount; i++)
{
B* p[nArraySize];
for (int j=0; j<nArraySize; j++)
{
p[j] = new B;
}
for (int j=0; j<nArraySize; j++)
{
delete p[j];
}
}
end2 = time(0);
begin1 = time(0);
for (unsigned int i=0; i<nLoopCount; i++)
{
A* p[nArraySize];
for (int j=0; j<nArraySize; j++)
{
p[j] = new A;
}
for (int j=0; j<nArraySize; j++)
{
delete p[j];
}
}
end1 = time(0);
printf("Without object pool: %u\n", end1-begin1);
printf("With object pool: %u\n", end2-begin2);
B::fini();
return 0;
}
# Filename: ObjectPool.cpp
# Writed by yijian on 2005-06-03
# Make test codes
x: x.cpp ObjectPool.cpp ObjectPool.h
g++ -g -o x x.cpp ObjectPool.cpp -I.
clean:
rm -f x |
|