三、定长内存池

三、定长内存池

我们知道申请内存使用的是malloc,malloc其实就是一个通用的大众货,什么场景下都可以使用,而什么场景下都可以用就意味着什么场景下都不会有很高的性能,下面我们就先来设计一个定长内存池作为一个开胃菜,当然这个定长内存池在后面的高并发内存池中也是有价值的,所以学习他目的有两层,第一是先熟悉一下简单内存池是如何控制的,第二是它会作为我们后面内存池的一个基础组件。

在这里插入图片描述

#pragma once#include <iostream>
#include <assert.h>
using std::cout;
using std::endl;#include "Common.h"#ifdef _WIN32
#include <windows.h>
#endif // _WIN32inline static void* SystemAlloc(size_t Kpage)
{
#ifdef _WIN32void* ptr= VirtualAlloc(0, Kpage * (1 << 13), MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
#else//其他环境
#endif // _WIN32if (ptr == nullptr){throw std::bad_alloc();}return ptr;
}template <class T>
class ObjectPool
{
public:T* New(){T* obj = nullptr;//如果在自由链表中有还回来的内存块,则优先使用if (_freeList != nullptr){//从_freeList链表头删一个内存块,顺便返回//_freeList指向的是自由链表的头上的小对象,这个小对象//的前4个或者8个字节(看机器环境)存放着下一个小对象的地址//*(void**)就拿到了下一个小对象的地址void* next = *(void**)_freeList;//取_freeList自由链表的头上T类型大小个字节赋值给obj即可obj = (T*)_freeList;//把_freeList更新为next相当于在_freeList中头删一个小对象_freeList = next;}else{//如果剩余的内存不够一个对象的大小,则需要重新向堆申请内存if (_RemainBytes < sizeof(T)){_RemainBytes = 128 * 1024;//_memory = (char*)malloc(_RemainBytes);//按页为单位向堆申请内存,一页8k,1k是1024字节,所以一页是2^13次方字节//所以字节数_Remaintypes右移13位就得到页数//直接调用系统调用接口SystemAlloc向堆申请内存,使它完全脱离开malloc函数_memory = (char*)SystemAlloc(_RemainBytes >> 13);if (_memory == nullptr){//申请内存失败就抛异常throw std::bad_alloc();}}//在_memory中切一个T类型大小的对象给objobj = (T*)_memory;//如果T的的大小太小的话就要多给一点内存,使它拥有能够放下一个指针变量大小的空间size_t objSize = sizeof(T) > sizeof(void*) ? sizeof(T) : sizeof(void*);//切走了一块空间就要使地址+=一个对象大小_memory += objSize;//剩余的字节数也要-=一个对象的大小_RemainBytes -= objSize;}//对已有的内存,利用定位new调用T的默认构造函数初始化new(obj)T;return obj;}void Delete(T* obj){//显式调用T的析构函数清理还回来的内存块的资源obj->~T();//把还回来的内存块头插到自由链表中*(void**)obj = _freeList;_freeList = obj;}
private:char* _memory = nullptr;//向堆申请的大块内存void* _freeList = nullptr;//用完之后还回来的内存块连接而成的自由链表size_t _RemainBytes = 0;//申请的大块内存用过之后剩余的字节数
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/62642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang 中的 crypto/ecdh 包详解

什么是 ECDH 算法&#xff1f; ECDH&#xff08;Elliptic Curve Diffie-Hellman&#xff09;算法是一种基于椭圆曲线的密钥交换协议&#xff0c;用于安全地协商共享密钥&#xff08;Secret Key&#xff09;&#xff0c;步骤如下&#xff1a; 1. 选择椭圆曲线&#xff1a;ECDH…

linux字符串处理

目录 1. C 截取字符串,截取两个子串中间的字符串linux串口AT指令 2. 获取该字符串后面的字符串用 strstr() 函数查找需要提取的特定字符串&#xff0c;然后通过指针运算获取该字符串后面的字符串用 strtok() 函数分割字符串&#xff0c;找到需要提取的特定字符串后&#xff0c;…

HTML/CSS盒子模型

盒子&#xff1a;页面中的所有的元素&#xff08;标签&#xff09;&#xff0c;都可以看做一个盒子&#xff0c;由盒子将页面中的元素包含在一个矩形区域内&#xff0c;通过盒子的视角更加方便的进行页面布局 盒子模型的组成&#xff1a; 内容区域&#xff08;content&#xff…

简单使用_matlab生成数据帧

文章目录 生成数据帧参考 生成数据帧 代码如下&#xff0c;代码很简单&#xff0c;有几点要注意&#xff0c; 较高版本的MATLAB中支持0x的写法使用bitand进行位运算使用strcat函数进行字符串拼接时&#xff0c;如果需要插入空格&#xff0c;要使用双引号 cmd_ay(1) 0x33; …

硬件性能评估指标-DMIPS、MFLOPS、MAC、TOPS

硬件性能评估指标-DMIPS、MFLOPS、MAC、TOPS DMIPS&#xff08;Dhrystone Million Instructions Per Second&#xff09;&#xff1a; DMIPS用于衡量计算机系统的整体指令执行性能&#xff0c;通常关注整数操作。它基于Dhrystone基准测试来计算&#xff0c;该测试主要包含整数运…

Android 进阶——图形显示系统之VSync和 Choreographer的创建详解(一)

引言 前一篇文章Android 进阶——图形显示系统之底层图像显示原理小结(一)介绍了关于Android 图形显示系统的基础理论,相信你对于Android的图形显示系统中图形界面渲染刷新机制有了更深的了解,接下来进一步讲解VSync和Choreography的联系和作用。 一、VSync 信号的产生概…

需求管理系统大盘点,谁能问鼎行业王者宝座?

“需求管理系统有哪些&#xff1f;这些品牌引领行业新风潮&#xff1a;Zoho Projects、SAP SuccessFactors、Oracle NetSuite、Microsoft Dynamics 365、Infor CloudSuite、JDA Software。” 需求管理系统是一种专门用于收集、分析和跟踪客户需求的工具&#xff0c;可以帮助企业…

总线:特性、分类、性能指标、系统总线的结构、总线仲裁、总线定时、总线标准

总线&#xff08;Bus&#xff09;&#xff0c;是一组为各功能部件之间进行信息传送的公共线路。 总线的特性&#xff1a; 机械特性&#xff08;物理特性&#xff09;&#xff1a;尺寸、形状、引脚数、排列顺序。电气特性&#xff1a;每根信号线上的信号传输方向、表示信号有效…

交换机 路由器的常见指令

常用的指令 交换机和路由器是网络中最常见的设备之一&#xff0c;它们都有一些常用的指令。下面是它们的常用指令和解释&#xff1a; 交换机常用指令 show interfaces&#xff1a;显示交换机上的所有接口信息&#xff0c;包括状态、速率、错误信息等。show mac-address-tabl…

deepspeed学习资料

记录一些deepspeed学习过程中的好文章 【进行中】1、DeepSpeed使用指南(简略版)_Reza.的博客-CSDN博客 - 含deepspeed的安装方法 - 含 zero config的不同配置&#xff0c;stage1、stage2、stage3的配置和解释

Go实现LogAgent:海量日志收集系统【上篇——LogAgent实现】

Go实现LogAgent 项目架构图&#xff1a; 0 项目背景与方案选择 背景 当公司发展的越来越大&#xff0c;业务越来越复杂时&#xff0c;每个业务系统都有自己的日志。此时我们就应该将不同业务线的日志进行实时收集&#xff0c;存储到一个日志收集中心&#xff0c;最后再通过…

H5 + C3基础(六)(2D转换transform 位移 旋转 缩放)

2D转换transform & 2D转换transform平移利用平移百分比优化盒子水平垂直居中 旋转指定2d变换的中心点 transform-origin 缩放2d转换简写 2D转换transform 所谓2D转换&#xff0c;就是在二维坐标系内进行各种操作&#xff0c;包括平移&#xff0c;转动&#xff0c;缩放等等…

Spring Security 中多个身份验证

如果你希望只要一个身份验证通过&#xff0c;就不再继续运行下一个身份验证配置&#xff0c;你可以使用 Spring Security 中的 AuthenticationManager 和 ProviderManager 来实现这一点。 ProviderManager 是 Spring Security 的核心组件之一&#xff0c;负责管理一系列的身份…

RecyclerView的局部刷新居然这么简单

RecyclerView的局部刷新 面试时经常被问到Android列表控件RecyclerView&#xff0c;无非就是深入源码与ListView进行对比&#xff0c;四层缓存和局部刷新。而今天的重点就是局部刷新 使用场景 我们在使用RecyclerView的局部刷新时&#xff0c;往往使用notify相关方法&#xff…

Android studio 软件git使用

在 test 分支添加的方法 , 现在切换到 master分支 总共 2 个分支 , 当前的分支是 test 出现了 先试一下 force checkout , 尝试之后发现 , 你更改没有带过来 , 以为哪个类在master分支没有 , 所以这边也没有 , 切回分支 test 发现之前的跟改没有 , 这样即可以找回 继续切换…

MySQL—MySQL主从如何保证强一致性

一、前言 涉及到的东西&#xff1a;两阶段提交&#xff0c;binlog三种格式 1、两阶段提交 在持久化 redo log 和 binlog 这两份日志的时候&#xff0c;如果出现半成功的状态&#xff0c;就会造成主从环境的数据不一致性。这是因为 redo log 影响主库的数据&#xff0c;binlog…

Java设计模式:一、六大设计原则-02:开闭原则

文章目录 一、定义&#xff1a;开闭原则二、模拟场景&#xff1a;开闭原则2.0 工程结构2.1 定义面积计算接口2.2 面积计算实现类 三、违背方案&#xff1a;开闭原则四、改善代码&#xff1a;开闭原则4.1 扩展继承4.2 单元测试 一、定义&#xff1a;开闭原则 开闭原则&#xff…

python爬虫—requests

一、安装 pip install requests 二、基本使用 1、基本使用 类型 &#xff1a; models.Response r.text : 获取网站源码 r.encoding &#xff1a;访问或定制编码方式 r.url &#xff1a;获取请求的 url r.content &#xff1a;响应的字节类型 r.status_code &#xff1a;响应…

Python入门学习——Day2-变量和数据类型

一、Python 变量 在Python中&#xff0c;变量用于保存数据&#xff0c;方便程序对数据的处理和操作。下面是关于Python变量的一些重要概念&#xff1a; 变量命名规则&#xff1a; 变量名由字母、数字和下划线组成。变量名可以以字母或下划线开头&#xff0c;但不能以数字开头…

界面控件DevExpress WinForms(v23.2)下半年发展路线图

本文主要概述了官方在下半年&#xff08;v23.2&#xff09;中一些与DevExpress WinForms相关的开发计划&#xff0c;重点关注的领域将是可访问性支持和支持.NET 8。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能…