高并发内存池: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;
};

感谢支持,长期连载

欢迎关注

相关推荐
Larcher4 小时前
React Router 不只是页面跳转:从 SPA 路由到权限守卫的完整实践
javascript·后端
Larcher4 小时前
大模型为什么每次回答都不一样?一文搞懂 Temperature、Top K 与 Top P
javascript·后端
·薯条大王7 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
用户938515635077 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformer.js 全链路实战
前端·设计模式·typescript
CodeSheep7 小时前
稚晖君公司人事大变动,来了!
前端·后端·程序员
鱼樱前端7 小时前
用 AI 做内容变收入
前端·人工智能·ai编程
eric-sjq8 小时前
10 分钟实战:用 0.6B 本地模型生成中文网页(WanlyFrontend + 编译器全流程)
javascript·机器学习·自然语言处理·html
浮生望8 小时前
React + TypeScript 组件设计进阶:从类型约束到无状态组件的三次进化
前端
To_OC8 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
90后的晨仔8 小时前
Mac 开发 uni-app 终极方案:让安卓模拟器彻底脱离 Android Studio 独立运行
前端·vue.js