~对象池
#ifndef __object_pool__
#define __object_pool__
#pragma once
#include "mutex_lock.h"
#define STRUCT_FIELD(address, type, field) ((type *)((char*)(address) - (size_t)(&((type *)0)->field)))
#define FIELD_STRUCT(address, type, field) ((type *)((char*)(address) + (size_t)(&((type *)0)->field)))
/*
对象池设计原理
list--------|tag|tag|tag|tag|tag-----100个|
list.next--------下一个list
tag---------tag---------tag--------下一个tag(这些tag都在list中)
tag.obj----------真正的obj对象
*/
template<typename OBJTYPE>
class object_pool
{
#define _OBJ_STEP 100
public:
object_pool() {__init();}
~object_pool() {__uninit();}
OBJTYPE* pop(){return __pop();}
bool push(OBJTYPE*& pobj) {return __push(pobj);}
private:
void __init()
{
m_phead = 0;
m_plist = 0;
m_cur_count = 0;
m_free_count = 0;
}
void __uninit()
{
c_mutex mutex(&m_lock);
tag_obj_list* plist = m_plist, *qlist = 0 ;//删除list
while(plist)
{
qlist = plist->next;
delete plist;
plist = qlist;
}
m_phead = 0;
m_plist = 0;
m_cur_count = 0;
m_free_count = 0;
}
bool __push(OBJTYPE*& pobj)
{
if(!pobj) return false;
tag_obj* ptag = FIELD_STRUCT(pobj,tag_obj,obj);
c_mutex mutex(&m_lock);
if(!ptag || ptag->b_in_pool) return false;
//头插法
if(m_phead)
{
ptag->next = m_phead;
m_phead = ptag;
}
else
{
m_phead = ptag;
ptag->next = 0;
}
pobj = 0;
ptag->b_in_pool = true;
m_free_count++;
printf("obj_pool push free_count=%d cur_count=%d\n",m_free_count,m_cur_count);
return false;
}
OBJTYPE* __pop()
{
c_mutex mutex(&m_lock);
if(!m_phead && !__create_block()) return 0;
//头取法
tag_obj* ptag = m_phead;
m_phead = m_phead->next;
ptag->b_in_pool = false;
m_free_count--;
printf("obj_pool pop free_count=%d cur_count=%d\n",m_free_count,m_cur_count);
return (OBJTYPE*)STRUCT_FIELD(ptag,tag_obj,obj);
}
bool __create_block()
{
tag_obj_list* plist = new tag_obj_list;
if(!plist) return false;
if(m_plist)
{
plist->next = m_plist;
m_plist = plist;
}
else
{
m_plist = plist;
m_plist->next = 0;
}
for(int i = 0; i< _OBJ_STEP;i++) //创建100个obj
{
plist->list[i].b_in_pool = false;
plist->list[i].next = 0;
OBJTYPE* q = &(plist->list[i].obj);
if(__push(q)) return false;
m_cur_count++; //放入成功 cur_count+1
}
return true;
}
private:
#pragma pack(push,1)
struct tag_obj
{
OBJTYPE obj;
bool b_in_pool;
tag_obj* next;
};
struct tag_obj_list{
tag_obj_list* next;
tag_obj list[_OBJ_STEP];
};
#pragma pack(pop)
mutex_lock m_lock;
tag_obj* m_phead;
tag_obj_list* m_plist;
int m_cur_count;
int m_free_count;
};
#endif
~内存池
#ifndef __mem_pool__
#define __mem_pool__
#pragma once
#include "mutex_lock.h"
#include "comm.h"
#define SHRINK_SPACE 1000*5 //内存池缩减时间间隔
#define SHRINK_COUNT 10 //每次缩减个数
#define SHRINK_TIME 1000 //内存空闲多长时间可释放
//c++中new开辟内存时会额外开辟数据头记录相关信息,以便在删除内存时知道需要删除多少 /tag/mem/tag/mem
typedef void TBLOCK;
#pragma pack(push,1)
struct tagblock
{
int size:31; //开辟内存大小
int status:1; //是否在池中
_uint32 code; //校验码
_uint32 utime; //buff创建时间
TBLOCK* next; //下一个buff
tagblock()
{
size = 0;
status = 0;
code = 0;
utime = 0;
next = 0;
}
};
#pragma pack(pop)
namespace comm_tblock
{
static _uint32 _code(tagblock* ptag)
{
return size_t(&ptag->code);
}
static tagblock* _head_tblock(TBLOCK* p)
{
return (p ? (tagblock*)((char*)p - sizeof(tagblock)): NULL);
}
static int _tblock_size(TBLOCK* p)
{
tagblock* ptag = _head_tblock(p);
return ptag ? ptag->size : 0;
}
static void _free_tblock(TBLOCK* p)
{
delete ((char*)p - sizeof(tagblock));
}
static TBLOCK* _create_tblock(int size)
{
if(size <= 0) return 0;
char* pbf = new char[sizeof(tagblock) + size];
if(!pbf) return 0;
tagblock* ptag = (tagblock*)pbf;
memset(ptag, 0, sizeof(tagblock));
ptag->size = size;
ptag->code = _code(ptag);
return (TBLOCK*)((char*)ptag + sizeof(tagblock));
}
static tagblock* _check_tblock(TBLOCK* p)
{
tagblock* ptag = _head_tblock(p);
return (!ptag || (ptag->code != _code(ptag))) ? 0 : ptag;
}
static TBLOCK* _bf_get_next(TBLOCK* p)
{
tagblock* ptag = _head_tblock(p);
return (ptag ? ptag->next : 0);
}
static bool _bf_set_next(TBLOCK* p,TBLOCK* q)
{
tagblock* ptag = _head_tblock(p);
if(!ptag) return false;
ptag->next = q;
return true;
}
};
//根据TBLOCK指针找到tagblock
#define _HEAD_TBLOCK(p) comm_tblock::_head_tblock(p)
//计算tagblock.code
#define _CODE(p) comm_tblock::_code(p)
//释放TBLOCK
#define _FREE_TBLOCK(p) comm_tblock::_free_tblock(p)
//创建TBLOCK
#define _CREATE_TBLOCK(size) comm_tblock::_create_tblock(size)
//设置后一个TBLCOK
#define _TBLOCK_GET_NEXT(p) comm_tblock::_bf_get_next(p)
//设置后一个TBLCOK
#define _TBLOCK_SET_NEXT(p,q) comm_tblock::_bf_set_next(p,q)
//检测tagblock.code
#define _CHECK_TBLOCK(p) comm_tblock::_check_tblock(p)
//block大小
#define _TBLOCK_SIZE(p) comm_tblock::_tblock_size(p)
class block_pool
{
public:
block_pool();
~block_pool();
bool init(int block_size,int init_count);
void uninit();
TBLOCK* pop(); //取出一个TBLOCK
bool push(TBLOCK*& p); //放入一个TBLOCK
void shrink(_uint32 * now_msec = 0); //定时释放空闲内存块
int block_size() {c_mutex mutex(&m_lock); return m_block_size;}
int cur_count() {c_mutex mutex(&m_lock); return m_cur_count;}
int free_count() {c_mutex mutex(&m_lock); return m_free_count;}
private:
bool new_block();
private:
mutex_lock m_lock;
TBLOCK* m_p_list_head; //指向内存链表第一个TBLOCK
TBLOCK* m_p_list_tail; //指向内存链表最后TBLOCK
int m_block_size; // TBLOCK大小
int m_cur_count; //当前TBLOCK数量
int m_free_count; //空闲TBLOCK数量
_uint32 m_last_shrink_time; //上次释放空闲内存时间
};
#define BFTYPE_COUNT 20 //类型个数
#define BFTYPE_64B 64 // 0
#define BFTYPE_128B 128 // 1
#define BFTYPE_256B 256 // 2
#define BFTYPE_512B 512 // 3
#define BFTYPE_1K 1024 // 4
#define BFTYPE_2K 2048 // 5
#define BFTYPE_4K 4096 // 6
#define BFTYPE_8K 8192 // 7
#define BFTYPE_16K 16384 // 8
#define BFTYPE_32K 32768 // 9
#define BFTYPE_64K 65536 // 10
#define BFTYPE_128K 131072 // 11
#define BFTYPE_256K 262144 // 12
#define BFTYPE_512K 524288 // 13
#define BFTYPE_1M 1048576 // 14
#define BFTYPE_2M 2097152 // 15
#define BFTYPE_4M 4194304 // 16
#define BFTYPE_8M 8388608 // 17
#define BFTYPE_16M 16777216 // 18
#define BFTYPE_32M 33554432 // 19
//内存池原理 预开辟多个内存块链表 开放接口取出放回指定长内存块
class block_pool_ex
{
public:
block_pool_ex();
~block_pool_ex();
TBLOCK* pop(_uint32 size);
bool push(TBLOCK* p);
void shrink(_uint32* now_msec = 0);
private:
inline int _index(_uint32 size);
block_pool m_pool_list[BFTYPE_COUNT];
};
#endif