当前位置:网站首页>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
边栏推荐
- Talk about how the kotlin process started?
- ACM intensive training graph theory exercise 3 in the summer vacation of 2020 [problem solving]
- Row column (vertical and horizontal table) conversion of SQL
- Express get request
- Solution to the eighth training competition of 2020 Provincial Games
- Deep Learning with Pytorch- neural network
- 2021-10-20
- Summary of Android knowledge points and common interview questions
- JVM garbage collector G1 & ZGC details
- Review the old and know the new
猜你喜欢
7. know JNI and NDK
Recommend a very easy-to-use network communication framework HP socket
小程序手持弹幕的原理及实现(uni-app)
About the smart platform solution for business hall Terminal Desktop System
What kind of experience is it to develop a "grandson" who will call himself "Grandpa"?
12. problem set: process, thread and JNI architecture
Express file upload
[wechat applet] realize applet pull-down refresh and pull-up loading
JVM garbage collector G1 & ZGC details
Acquisition de 100% des actions de Guilin latex par Guilin Robust Medical pour combler le vide de la gamme de produits Latex
随机推荐
Tclistener server and tcpclient client use -- socket listening server and socketclient use
Talk about the job experience of kotlin cooperation process
Initialize static resource demo
Distributed ID
八大排序(一)
Idea shortcut key settings
JVM garbage collector G1 & ZGC details
Using OpenCV Net for image restoration
I'm late for school
Enum demo
Express - static resource request
Flutter 0001, environment configuration
仿照微信Oauth2.0接入方案
Simple redis lock
Express の post request
What are the SQL add / delete / modify queries?
Common query and aggregation of ES
JVM notes (III): analysis of JVM object creation and memory allocation mechanism
Installation, use and explanation of vulnerability scanning tool OpenVAS
Deeply understand the working principle of kotlin collaboration suspend (beginners can also understand it)