高并发内存池:Part-1——定长内存池

@bit::Shadow
✧(≖ ◡ ≖✿

目录

定长内存池

一:New()的初步设计

二:Delete()的设计

为什么不回退_memory?

完整代码gitee


定长内存池

有效、可分配内存块有两部分

1.有效内存池块。

2.自由链表管理区域。

构造函数

划分128kB给ObjectPool对象,异常抛出std::bad_alloc()。

New:为特定类型通过自由链表存储的/池内,分配固定空间大小。

Delete(const T* t):销毁指定目标。

一:New()的初步设计

_remainBytes:内存块内(自由链表内不计入大小)的剩余字节。

cpp 复制代码
//申请
T* New()
{
	int _sz = sizeof(T);
	//块内分配
	if (_remainBytes <= _sz)
	{
		//剩余不足,新开大块
		Alloc();//内存碎片问题不计
	}
	T* obj = (T*)_memory;
	_memory += _sz;
	_remainBytes -= _sz;

	return obj;
}

初步架构:

cpp 复制代码
template<typename T>
class ObjectPool//无并发性,外界统一接口?
{
private:
	void Alloc()//bool?抛异常与bool分隔。bool会增加处理成本
	{
		//划分块
		_memory = (char*)malloc(128 * 1024);//1.此处malloc不够纯粹,"其底层封装"(划掉)
								//※			//2.使用SystemAlloc更纯粹,后期对比效率时替换
		if (!_memory)
			throw std::bad_alloc();//大块划分失败,怎么捕捉?与构造函数无关?
		_remainBytes = 128 * 1024;//※
	}

public:
	ObjectPool()
		:_memory(nullptr), _remainBytes(0)
	{ 
		Alloc();
	}
	//**成员先走初始化列表,后走函数体内**

	//申请
	T* New()
	{
		int _sz = sizeof(T);
		//块内分配
		if (_remainBytes <= _sz)
		{
			//剩余不足,新开大块
			Alloc();//内存碎片问题不计
		}
		T* obj = (T*)_memory;
		_memory += _sz;
		_remainBytes -= _sz;
        
        return obj;
	}
private:
	char* _memory;//内存块头指针(128kB)
	int _remainBytes;//内存块内(自由链表内不计入大小)的剩余字节
};

二:Delete()的设计

被删除任务删除头插进自由链表,由_freeList管理。

为什么不回退_memory?

销毁对象内存不一定连续。

设计图示

cpp 复制代码
//释放,自由链表回收♻️
void Delete(const T* t)
{
	//头插
	*(void**)t = _freeList;
	//_freeList = t;//原因分析
	_freeList = const_cast<T*>(t);
}

✨亮点:

1.为兼容x64、x86系统使用指针这一随系统大小变换的类型作为,限制访问区域。

2.const_cast<template T> (T t); 去const属性 // 非std域!!

完整代码gitee

cpp 复制代码
#pragma once
//using namespace std::
#include<iostream>

/*
设计原则:
1.模板元编程。基于T大小申请、管理内存块。
意味着:
单一类型对象,New固定T大小无法指定。不像(void*) maollc(sizeof(size_t size))
2.定长内存池设计的目标是:体会"池化技术",这一高效、广泛应用技术的底层设计原理。

//严格遵循"高内聚,低耦合"特性
*/
template<typename T>
class ObjectPool//无并发性
{
private:
	void Alloc()//bool?抛异常与bool分隔。bool会增加处理成本
	{
		//划分块
		_memory = (char*)malloc(128 * 1024);//1.此处malloc不够纯粹,"其底层封装"(划掉)
								//※			//2.使用SystemAlloc更纯粹,后期对比效率时替换
		if (!_memory)
			throw std::bad_alloc();//大块划分失败,怎么捕捉?与构造函数无关?
		_remainBytes = 128 * 1024;//※
	}

	T* FreeAlloc()
	{
		//自由链表分配
		//if (!_freeList)//err
		if (_freeList)
		{
			T* obj = _freeList;
			//头删
			_freeList = *(void**)_freeList;

			_remainBytes = _remainBytes;
			return obj;
		}
		return nullptr;
	}
public:
	ObjectPool()
		:_memory(nullptr), _remainBytes(0), _freeList(nullptr)
	{ 
		Alloc();
	}
	//**成员先走初始化列表,后走函数体内**

	//申请
	T* New()
	{
		//1.自由链表分配
		return FreeAlloc();

		//int _sz = sizeof(T);因为自由链表要管理,所以至少给4/8
		int _sz = sizeof(T) >= sizeof(T*) ? sizeof(T) : sizeof(T*);

		//dpsk:一个类型T*的指针管理T的空间与管理4T空间有什么区别?
		// 访问限制、算术法固定
		
		//2.块内分配
		if (_remainBytes <= _sz)
		{
			//剩余不足,新开大块
			Alloc();//内存碎片问题不计
		}
		T* obj = (T*)_memory;//
		_memory += _sz;
		_remainBytes -= _sz;

		return obj;
	}

    //释放,自由链表回收♻️
	void Delete(const T* t)
	{
		//头插
		*(void**)t = _freeList;
		//_freeList = t;//原因分析
		_freeList = const_cast<T*>(t);
	}
private:
	char* _memory;//内存块头指针(128kB)
	int _remainBytes;//内存块内(自由链表内不计入大小)的剩余字节

	T* _freeList;//自由链表头
};

//测试类型T
class TreeNode
{
private:
	int _val;
	TreeNode* _left;
	TreeNode* _right;
};

感谢支持,长期连载

欢迎关注

相关推荐
m0_587383005 分钟前
无人自助拼豆系统核心功能开发与部署落地全流程实战指南
java·经验分享·后端·struts·架构
独孤九剑打醒他6 分钟前
【原创开源·航空终极篇】氢能航空动力升级:双燃料掺氢、富氧补气与露天储氢安全模型
前端·架构·开源·硬件工程·能源
律宏阔9 分钟前
阿里云 ESA + Pages 域名部分电脑无法访问
前端
Lank_M13 分钟前
canvas 第一次画字没用上字体,字体却是它要来的
前端
雷一言说14 分钟前
Spring AI 2.0:RAG 文档分块大小策略选择
java·spring
XIAEE14 分钟前
Java 世界历险记:从一行 System.out.println 到整个 Spring 宇宙
java·spring
XIAEE16 分钟前
微前端狂想曲:我试图让三个不同门派的前端住进同一栋楼
java·spring
古夕17 分钟前
iframe 授权失败时露出 60000 JSON 的复盘
前端·javascript
XIAEE17 分钟前
Linux 生存指南:从"终端恐惧症"到"命令行老司机"
java·spring
XIAEE17 分钟前
实战教程:手机端死活调不出摄像头?聊聊安全上下文(Secure Context)
java·spring