当前位置:网站首页>utlis 内存池 对象池
utlis 内存池 对象池
2022-06-30 09:32:00 【Zip-List】
utils 内存池
内存池负责管理多个对象池,对象池负责管理多个对象
空间非连续,用时分配
对象池
对象池类的变量 map<mid_t, T*>负责记录正在使用的内存映射,POD类型的对象池,size时确定的
class UNIT_POOL_BASE
{
public:
virtual mid_t alloc_unit() = 0;
virtual void free_unit(mid_t mid) = 0;
virtual void* get_unit(mid_t mid) = 0;
virtual int get_cur_use_num() = 0;
public:
u16 _type; // pool type
int _num_limit; // 数量限制
int _unit_size; // 单个unit大小
int _max_used; // 最大用了多少个
std::string _type_name; // type name
};
template<typename T>
class UNIT_POOL : UNIT_POOL_BASE
{
public:
typedef typename std::map<mid_t, T*>::iterator IT;
UNIT_POOL()
{
_map_use.clear();
_num_limit = 0;
_max_used = 0;
_type_name = "";
}
~UNIT_POOL()
{
for (auto& itr : _map_use)
{
if (itr->second)
{
delete (itr->second); //delete 指针时会调用指针所指对象的析构函数
}
}
_map_use.clear();
}
virtual mid_t alloc_unit();
virtual void free_unit(mid_t mid);
virtual void* get_unit(mid_t mid);
virtual int get_cur_use_num();
private:
std::map<mid_t, T*> _map_use; // 正在使用的内存映射
};
小技巧,使用位域在按type分配时,加入序列号信息。对象记录了自己的type可以反查到对应对象池的信息
typedef struct unitmid_t
{
u64 type : 16;
u64 serial : 48;
} unitmid_t;
inline mid_t alloc_mid(u16 type)
{
static u64 base_id = 10000;
++base_id;
unitmid_t unit_mid;
#pragma GCC diagnostic ignored "-Wconversion"
unit_mid.type = type;
unit_mid.serial = base_id;
#pragma GCC diagnostic pop
return *(mid_t *)&unit_mid;
}
相应函数实现 分配对象 获取对象 释放对象
template<typename T>
mid_t UNIT_POOL<T>::alloc_unit()
{
if (_num_limit <= (int)_map_use.size())
{
fatal_log("type:%d type_name:%s alloc fail, cur use:%d upper limit exceeded"
, _type, _type_name.c_str(), (int)_map_use.size());
return INVALID_MID;
}
void* data = malloc(_unit_size);
assert_retval(data, INVALID_MID);
// placement new
memset((char*)data, 0x00, _unit_size);
T* ptr = new(data) T;
assert_retval(ptr != nullptr, INVALID_MID);
mid_t mid = alloc_mid(_type);
_map_use[mid] = ptr;
if (_max_used < (int)_map_use.size())
{
_max_used = (int)_map_use.size();
}
return mid;
}
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
template<typename T>
void UNIT_POOL<T>::free_unit(mid_t mid)
{
IT itr = _map_use.find(mid);
if (itr == _map_use.end())
{
return;
}
T* ptr = itr->second; // 在已分配存储中构造(“布置”)
_map_use.erase(itr);
assert_retnone(ptr);
ptr->~T(); // free并不会调用对象的析构,要手动调用
// free
free((void*)ptr);
}
#pragma GCC diagnostic warning "-Wdelete-non-virtual-dtor"
template<typename T>
void* UNIT_POOL<T>::get_unit(mid_t mid)
{
IT itr = _map_use.find(mid);
if (itr == _map_use.end())
{
return nullptr;
}
return itr->second;
}
template<typename T>
int UNIT_POOL<T>::get_cur_use_num()
{
return (int)_map_use.size();
}
内存池
对象池根据编号管理对应的对象池
std::map<int, UNIT_POOL_BASE*> g_map_pool; //全局的内存池 装有对象池的地址
相应函数封装 分配对象 获取对象 释放对象
/** @brief 内存池初始化和回收,进程启动和退出时调用 */
int mempool_init();
void mempool_fini();
/** @brief 对象类型注册 @param[in] type -- 内存对象类型 @param[string] type_name -- 内存type名字 @param[in] num_limit -- 内存数量限制 @param[UNIT_POOL_BASE] pool_fn -- 内存对象管理指针 @retval 0 -- 成功 @retval <0 -- 失败 */
int unitpool_init(u16 type, const char* type_name, int num_limit, int unit_size, UNIT_POOL_BASE* unit_pool);
/** @brief 申请对象 // 申请对象,调用内存池中固定类型对象池的分配对象 @param[in] type -- 内存对象类型 @retval =INVALID_MID -- 失败 @retval 其他值-- 成功,对象的mid标志 */
mid_t memunit_alloc(u16 type);
/** @brief 对象释放 @param[in] type -- 内存对象类型 */
void memunit_free(mid_t mid);
/** @brief 获得对象内存地址 @param[in] type -- 内存对象类型 @retval =nullptr -- 失败,找不到该对象 @retval !=nullptr-- 成功,对象的内存地址 */
void* memunit_get(mid_t mid);
具体实现
int mempool_init()
{
g_map_pool.clear();
return 0;
}
void mempool_fini()
{
g_map_pool.clear();
}
int unitpool_init(u16 type, const char* type_name, int num_limit, int unit_size, UNIT_POOL_BASE* unit_pool)
{
assert_retval(unit_pool && type_name, BGERR_INVALID_ARG);
assert_retval(type >= 0 && type < MAX_POOL_TYPE_NUM, BGERR_INVALID_ARG);
assert_retval(num_limit > 0, BGERR_INVALID_ARG);
auto itr = g_map_pool.find(type);
if (itr != g_map_pool.end())
{
assert_retval(0, BGERR_INVALID_ARG);
}
unit_pool->_type = type;
unit_pool->_num_limit = num_limit;
unit_pool->_type_name = type_name;
unit_pool->_unit_size = unit_size;
g_map_pool[type] = unit_pool;
infor_log("unitpool init, type:%d name:%s num_limit:%d", type, type_name, num_limit);
return 0;
}
mid_t memunit_alloc(u16 type)
{
auto itr = g_map_pool.find(type);
if (itr == g_map_pool.end() || !itr->second)
{
assert_retval(0, INVALID_MID);
}
return itr->second->alloc_unit();
}
void memunit_free(mid_t mid)
{
unitmid_t *unitmid = (unitmid_t *)∣
int type = unitmid->type;
auto itr = g_map_pool.find(type);
if (itr == g_map_pool.end() || !itr->second)
{
//assert_retnone(0);
return;
}
itr->second->free_unit(mid);
}
void* memunit_get(mid_t mid)
{
unitmid_t *unitmid = (unitmid_t *)∣
int type = unitmid->type;
auto itr = g_map_pool.find(type);
if (itr == g_map_pool.end() || !itr->second)
{
//assert_retval(0, nullptr);
return nullptr;
}
return itr->second->get_unit(mid);
}
#define POOL_REGISTER(MEM_TYPE_ID, MEM_TYPE_NAME, MEM_STRUCT_TYPE, MEM_UNIT_NUM) \ do {
\ UNIT_POOL<MEM_STRUCT_TYPE>* unit_pool = new UNIT_POOL<MEM_STRUCT_TYPE>;\ if (nullptr == unit_pool)\ {
\ error_log("mem type: %s create register deal fn failed", #MEM_TYPE_ID); \ return BGERR_UNKNOWN; \ }\ int ret = bg_unitpool_init(MEM_TYPE_ID, MEM_TYPE_NAME, MEM_UNIT_NUM, sizeof(MEM_STRUCT_TYPE), (UNIT_POOL_BASE*)unit_pool);\ if (0 != ret)\ {
\ error_log("mem type: %s register deal fn failed, retval: %d", \ #MEM_TYPE_ID, BGERR_UNKNOWN); \ return ret; \ }\ }while(0)
思考
对象池用时分配,并未在连续空间上分配,如果连续空间要初始化时分配所有空间,对对象的管理可以使用map或者free_list记录,或者数组记录第几块被使用
连续空间如何防止边缘部分被写坏,非连续空间段错误,连续空间加入保护部分,转型使用dynamic_cast
边栏推荐
- Review the old and know the new
- Handwriting sorter component
- Function simplification principle: save if you can
- Applet learning path 2 - event binding
- Net framework system requirements
- List set export excel table
- Express get request
- Linear-gradient()
- Clickhouse installation (quick start)
- Invalid update: invalid number of sections. The number of sections contained in the table view after
猜你喜欢

Express file upload

Metasploit practice - SSH brute force cracking process

八大排序(二)
![[shutter] solve failed assertion: line 5142 POS 12: '_ debugLocked‘: is not true.](/img/77/eb66ec83b34c251e732d495fbaa951.jpg)
[shutter] solve failed assertion: line 5142 POS 12: '_ debugLocked‘: is not true.

Abstract factory pattern

Interviewer: do you understand the principle of recyclerview layout animation?

仿照微信Oauth2.0接入方案

Couldn't load this key (openssh ssh-2 private key (old PEM format))

asdsadadsad

Applet learning path 2 - event binding
随机推荐
What kind of experience is it to develop a "grandson" who will call himself "Grandpa"?
Express file download
ES6 learning path (IV) operator extension
Research on lg1403 divisor
Idea shortcut key settings
Express file upload
Guilin robust medical acquired 100% equity of Guilin Latex to fill the blank of latex product line
2020-11-02
Abstract factory pattern
Talk about how the kotlin process started?
Why won't gold depreciate???
【Ubuntu-redis安装】
Tablet PC based ink handwriting recognition input method
JVM tuning tool introduction and constant pool explanation
Niuke IOI weekly competition 20 popularization group (problem solving)
Get to know handler again
Express - static resource request
Review the old and know the new
Mysq database remote connection error, remote connection is not allowed
Numpy (data type)