C++ 实现Buffer 动态分配管理代码实现
发布日期:2021-06-29 14:50:54
浏览次数:3
分类:技术文章
本文共 7890 字,大约阅读时间需要 26 分钟。
C++ 实现Buffer 动态分配管理代码实现
应公司需求,花半天时间写了一个内存buffer 动态管理的代码,需兼顾 性能 和 内存(时间和空间)。
实现功能如下:- 初始化时,常驻两块 buff 用于数据传输。(兼顾 性能)
- 在数据高峰期时,当已分配的两块 buff 不够用时,能够实现动态的分配新的buff .
- 在数据低峰期时,之前分配的多余的 buff 会自动 free 掉,保证应用不会占用太大的内存。(兼顾 内存)
自动 free buff 的方案实现思路如下:
每个数据自带计数 unused_cnt,初始值为10,每过一秒自动减1, 当系统检测到 数值为0 时,说明 该buff 已长时间未使用,则调用 free 函数释放 buff。如下代码是下午写的完整的 buff 管理代码,为方便后续维护封装为 class 类,测试 ok ,已上代码库使用。
代码如下:
一、 Class Memory_Manager 头文件代码实现
@ /jni/include/receivedata.h#ifndef RECEIVEDATA#define RECEIVEDATA#include#include #include #include #include // signal#include "libmsdp.h"#include "msdp_type.h"#include #include // alarm#include #include #include "hicarnative.h"/// mem_alloc.cpp ///typedef struct Video_Buffer_t{ uint32_t lengh_buf; uint8_t *pbuf; bool is_ready; bool is_using; int unused_cnt; // 10: using 0: not using};#define BUFFER_NUM_INIT 2#define BUFFER_NUM_MAX 5 // max size is 1.3824M * 5 = 6.912M#define BUFFER_AUTO_CLEAR_TIME 10 // free unnecessary bufeer#define BUFFER_SIZE 1920*720 // 1,382,400class Memory_Manager{ public: Memory_Manager(); ~Memory_Manager(); void clear_buffer(int index); int get_null_buffer(void); int get_ready_buffer(int times); int push_buffer_data(const uint8_t *pPacket, uint32_t nPktSize); void pop_buffer_data(void); void alarm_work(); private: Video_Buffer_t video_buff[BUFFER_NUM_MAX]; int current_buff_num; //void free_buffer_alarm_fn(int sig);};extern Memory_Manager * mem_manager;//call delete mem_manager when not use/// END ///#endif
二、 Class Memory_Manager 代码实现
@ /jni/memory_manager.cpp#include "receivedata.h"void Memory_Manager::alarm_work(){ ALOGI_D("[Memory_Manager::alarm_work] enter "); if( current_buff_num > BUFFER_NUM_INIT) { for(int i = BUFFER_NUM_INIT; i0) && (NULL != video_buff[i].pbuf) && (0 == video_buff[i].lengh_buf)) { video_buff[i].unused_cnt = video_buff[i].unused_cnt -1; ALOGI_D("[free_buffer_alarm_fn] video_buff[%d].unused_cnt = %d ", i, video_buff[i].unused_cnt); } if( (video_buff[i].unused_cnt <= 0) && (NULL != video_buff[i].pbuf) && (0 == video_buff[i].lengh_buf)) { free(video_buff[i].pbuf); video_buff[i].pbuf = NULL; clear_buffer(i); current_buff_num--; } } } if(current_buff_num != BUFFER_NUM_INIT) alarm(1); }//TODO: add timer function here, check if need release buffervoid free_buffer_alarm_fn(int sig) { mem_manager->alarm_work(); return; } Memory_Manager::Memory_Manager(){ ALOGI_D("[Memory_Manager::Memory_Manager] enter "); current_buff_num = BUFFER_NUM_INIT; for(int i=0; i < BUFFER_NUM_INIT; i++){ // 0 1 clear_buffer(i); video_buff[i].pbuf = (uint8_t *) malloc(BUFFER_SIZE); } for(int i=BUFFER_NUM_INIT; i < BUFFER_NUM_MAX; i++){ // 2 3 4 clear_buffer(i); } signal(SIGALRM, free_buffer_alarm_fn);} Memory_Manager::~Memory_Manager(){ ALOGI_D("[Memory_Manager::~Memory_Manager] enter "); for(int i=0; i < current_buff_num; i++){ if((NULL != video_buff[i].pbuf)) free(video_buff[i].pbuf); video_buff[i].pbuf = NULL; clear_buffer(i); }}void Memory_Manager::clear_buffer(int index){ ALOGI_D("[Memory_Manager::clear_buffer] start clear video_buff_%d, size=%d +++ ", index , video_buff[index].lengh_buf); video_buff[index].is_ready = false; video_buff[index].is_using = false; video_buff[index].lengh_buf = 0; video_buff[index].unused_cnt = BUFFER_AUTO_CLEAR_TIME;}int Memory_Manager::get_null_buffer(void){ for(int i=0; i < current_buff_num; i++) { ALOGI_D("[Memory_Manager::get_null_buffer] is_ready=%d, is_using=%d, pbuf not null=%d, lengh_buf=%d, i=%d \n", video_buff[i].is_ready, video_buff[i].is_using, (NULL != video_buff[i].pbuf) ? 1 : 0, video_buff[i].lengh_buf, i ); if( ( false == video_buff[i].is_using) && (0 == video_buff[i].lengh_buf) && ( false == video_buff[i].is_ready) ) { ALOGI_D("[Memory_Manager::get_null_buffer] return index = %d +++ ", i); return i; } } /// TODO CHECK // Buffer is not enough, alloc a new one if(current_buff_num < BUFFER_NUM_MAX){ current_buff_num++; ALOGI_D("[Memory_Manager::get_null_buffer] Buffer is not enough, alloc a new one, current_buff_num=%d ", current_buff_num); clear_buffer( current_buff_num-1 ); //if( NULL == video_buff[ current_buff_num-1 ].pbuf ){ video_buff[ current_buff_num-1 ].pbuf = (uint8_t *) malloc(BUFFER_SIZE); //}else{ // ALOGI_D("[Memory_Manager::get_null_buffer] malloc error !!! video_buff[%d] is not NULL ", current_buff_num-1); //current_buff_num--; //} video_buff[ current_buff_num-1].unused_cnt = BUFFER_AUTO_CLEAR_TIME; // TODO: start a timer every 1s, Check if need free then alarm(1); return current_buff_num-1; } ALOGI_D("[Memory_Manager::get_null_buffer] current_buff_num=%d reach the max , let data go ", current_buff_num); return -1;}// get a data to uploadint Memory_Manager::get_ready_buffer(int times){ for(int i=0; i < current_buff_num; i++) { ALOGI_D("[Memory_Manager::get_ready_buffer] is_ready=%d, is_using=%d, pbuf not null=%d, lengh_buf=%d, i=%d \n", video_buff[i].is_ready, video_buff[i].is_using, (NULL != video_buff[i].pbuf) ? 1 : 0, video_buff[i].lengh_buf, i ); if( (true == video_buff[i].is_ready) && (false == video_buff[i].is_using) && (0 != video_buff[i].lengh_buf) ) { return i; } } if(times == 0) ALOGI_D("[Memory_Manager::get_ready_buffer] has no ready buff !!! "); return -1;}int Memory_Manager::push_buffer_data(const uint8_t *pPacket, uint32_t nPktSize){ int index; index = get_null_buffer(); if(index == -1){ return index; } //video_buff[index].pbuf = (uint8_t *) malloc(nPktSize); // this could be a malloc pool video_buff[index].lengh_buf = nPktSize; memcpy(video_buff[index].pbuf, (uint8_t *)pPacket, nPktSize); video_buff[index].is_ready = true; video_buff[index].is_using = false; ALOGI_D("[Memory_Manager::push_buffer_data] nPktSize = 2 %d", nPktSize); return 0;}void Memory_Manager::pop_buffer_data(void){ int index = get_ready_buffer(0); while( index != -1 ) { video_buff[index].is_using = true; sendVideoDataNative(video_buff[index].pbuf, video_buff[index].lengh_buf); memset(video_buff[index].pbuf , 0 , BUFFER_SIZE); clear_buffer(index); index = get_ready_buffer(1); }}
三、Class Memory_Manager 使用方法
在实例化 class Memory_Manager 后,使用者不需要操心 buff 的问题,
使用非常简单, 第一步:new 一个 class Memory_Manager 对象。 第二步:调用写数据接口,写数据 第三步:调用读数据接口,上报数据。当数据量比较大时,buff 内部如何对数据管理分配,完全由 class Memory_Manager 来实现。
@ /jni/libreceivedata.cpp#include "receivedata.h"Memory_Manager * mem_manager;1. 初始化代码 // ciellee 20191010 +++ mem_manager = new Memory_Manager(); // ciellee 20191010 ---2. 将数据写放一块 buff 中 // ciellee 20191010 +++ if( mem_manager->push_buffer_data(pPacket,nPktSize) == 0) { pthread_cond_signal(&mDataCondition); } // ciellee 20191010 ---3. 取出数据 // ciellee 20191010 +++ mem_manager->pop_buffer_data(); // ciellee 20191010 ---
转载地址:https://ciellee.blog.csdn.net/article/details/102488219 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月30日 20时54分54秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
2021.4.28课堂总结和作业
2019-04-29
2021.4.29课堂总结
2019-04-29
2021.4.30课堂总结和作业
2019-04-29
需要吗?2000GB+学习视频教程 面试资料免费下载
2019-04-29
MySQL对已存在数据库表添加自增ID字段
2019-04-29
idea中的一些常用快捷键
2019-04-29
js校验表单后提交表单的三种方法总结【转载】
2019-04-29
欢迎使用CSDN-markdown编辑器
2019-04-29
a标签中href调用js的几种方法
2019-04-29
jstl标签详解
2019-04-29
Eclipse中使用SVN的使用
2019-04-29
JSON.parse和eval的区别
2019-04-29
JQuery中$.ajax()方法参数详解
2019-04-29
正则表达式的数字实例
2019-04-29
OGNL表达式struts2标签“%,#,$”的区别
2019-04-29
struts2中<s:if>标签的使用
2019-04-29
js 刷新页面window.location.reload();
2019-04-29
【转】EasyUI 验证
2019-04-29