当前位置: 首页 > news >正文

高并发内存池(1)-定长内存池

高并发内存池(1)-定长内存池

可以采用两种方式:

方式1:

template <size_t N>

方式2:

template <class T>

获取到T对象大小的内存池,更推荐使用方式二,因为可以动态灵活调整类型

需要的成员变量:

_memory:表示一大块内存,需要确定使用的变量类型

能否使用void*?

*表示的是指针,指针代表的是地址,它的指向需要有意义, *的前面表示的是类型,void * 没有意义,既不能解引用又不能进行加减

解决方案就是换成char*,因为一个char表示一个字节,也可以用int之类的,但是不会方便,比如要是取3字节啥的

怎么管理需要还回来的链表?

用自由链表

怎么样去连接?

不用结构体,用其内存块当节点,用头四个或者八个节点存储下一个位置的地址,这时候需要处理如果只剩最后一个会不会越界的情况,这时候我们需要引入新的成员变量remianBytes来知道剩余内存的大小,

自由链表需要进行头插,注意类型是void*,因为void *在32位下是4字节,64位是八字节,不用写if else条件判断语句去判断

整体的代码如下:

#pragma once#include <iostream>
#include <vector>
#include <time.h>using std::cout;
using std::endl;#ifdef _WIN32
#include <windows.h>
#else
// ...
#endif// 直接去堆上按页申请空间
inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else// linux下brk mmap等
#endifif (ptr == nullptr)throw std::bad_alloc();return ptr;
}//定长内存池:每次获取到T对象大小的内存池
template <class T>
class ObjectPool
{public://对内存进行分配T* New(){//创建每次需要分配的内存块T* obj =nullptr;//优先使用自由链表里面的if (_freeList){//定义next指针void* next = *((void**)_freeList);obj = (T*)_freeList;_freeList = next;}//如果自由链表里面的不够了,再进行创建else{// 剩余内存不够一个对象大小时,则重新开大块空间if (remainBytes < sizeof(T)){//初始化remainBytes的大小remainBytes = 128 * 1024;//空间开辟大小,右移13相当于除以2的十三次方,2的10次方已经是1000多_memory = (char*)SystemAlloc(_remainBytes >> 13);//如果开创空间有异常就抛出异常if (_memory == nullptr){throw std::bad_alloc();}}//此时创建空间obj = (T*)_memory;//判断T对象的大小,void*在32位下是4字节,64位下是8字节size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);//切下空间_memory += objSize;//剩余空间去扣除相应的大小remainBytes -= objSize;}// 定位new,显示调用T的构造函数初始化,以防会调用如vector,string之类的new(obj)T();return obj;}//自由链表进行管理T* Delete(T*obj){// 显示调用析构函数清理对象obj->~T();// 头插,存前4个或者8个字节到下一节点*(void**)obj = _freeList;_freeList = obj;}private:char* _memory = nullptr;// 指向大块内存的指针size_t remainBytes = 0;// 大块内存在切分过程中剩余字节数void* _freeList = nullptr;// 还回来过程中链接的自由链表的头指针
};

整体的流程:先看freeList有没有空余的,先进行头删,然后再到_memory里面去切,如果没有多余的,就去找系统申请大块内存

如何释放?不需要释放,不需要担心内存是否会泄漏,因为只要进程结束,它也能正常释放

http://www.dtcms.com/a/348437.html

相关文章:

  • 阿里开源通义万相Wan2.2:视频生成技术的革命性突破
  • MR椎间盘和腰椎分割项目:基于深度学习的医学图像分析
  • Linux系统之Centos7安装cockpit图形管理界面
  • 项目学习总结(5)
  • python---构造函数、析构函数
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘gunicorn’问题
  • 【springboot 技术代码】集成mongodb 详细步骤
  • localhost和127.0.0.1的区别
  • 界面规范7-可左右拖动的分割条
  • MATLAB GUI 设计入门:用 Guide 工具快速搭建交互界面
  • React Hooks useEffect的使用
  • React 18+ 并发模式异常
  • Linux服务测试题(DNS,NFS,DHCP,HTTP)
  • pytorch线性回归(二)
  • ⭐CVPR2025 病理分析全能模型 CPath-Omni 横空出世
  • RAG智能问答为什么需要进行Rerank?
  • 春秋云镜 Flarum
  • UCIE Specification详解(二)
  • Linux学习-TCP网络协议
  • 基于springboot的高校后勤保修服务系统/基于android的高校后勤保修服务系统app
  • openFeign用的什么协议,dubbo用的什么协议
  • 【重学MySQL】八十七. 触发器管理全攻略:SHOW TRIGGERS与DROP TRIGGER实战详解
  • k8s下的网络通信之calico与调度
  • MySQL官方C/C++ 接口入门
  • 从栈到堆:深入理解C语言静态与动态链表的创建与管理
  • 利旧小天才儿童电话手表实现“一键寻车”功能
  • 线程整理文档
  • 使用UE5开发《红色警戒3》类战略养成游戏的硬件配置指南
  • 【Spring Cloud 微服务】3.智能路由器——深入理解与配置负载均衡
  • MySQL的更新语句执行过程涉及了哪些文件的写入,衍生了redo、undo、二进制日志在什么时候进行写入