[项目][CMP][定长内存池]详细讲解


0.铺垫

  • 作为程序员(C/C++)我们知道申请内存使用的是malloc,malloc其实就是一个通用的大众货,什么场景下都可以用,但是什么场景下都可以用就意味着什么场景下都不会有很高的性能
  • 下面就先设计 一个定长内存池做个开胃菜,当然这个定长内存池在后面的高并发内存池中也是有价值的,所以学习他目的有两层
    • 先熟悉一下简单内存池是如何控制的
    • 会作为后面内存池的一个基础组件
  • 定长内存池特点 – 固定大小的内存申请释放需求
    • 性能达到极致
    • 不考虑内存碎片等问题
  • Windows和Linux下如何直接向堆申请页为单位的大块内存:

1.理解

请添加图片描述

  • 定长内存池设计
    请添加图片描述

2.实现

// 说明
// 使用定长内存池替代malloc,否则CMP替代malloc,但是里面又调用malloc,死循环了:P
#pragma once
#include <iostream>
#include "Common.h"

// 定长内存池v1.0
//template<size_t N>
//class ObjectPool
//{};

// 因为每个对象大小是固定的,所以也可以这样设计
template<class T>
class ObjectPool
{
public:
	T* New()
	{
		T* obj = nullptr;
		// 优先用已经还回来的内存块
		if (_freeList)
		{
			obj = (T*)_freeList;
			_freeList = *(void**)_freeList;
		}
		else
		{
			// 剩余字节数少于一个对象大小,则重新申请大空间
			if (_remainBytes < sizeof(T))
			{
				_remainBytes = 128 * 1024;
				_memory = (char*)SystemAlloc(_remainBytes >> 13);
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}

			obj = (T*)_memory;

			// 可能T对象大小小于一个指针,此时若只使用一个T的大小,则存不下一个地址
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T); 
			_memory += objSize;
			_remainBytes -= objSize;
		}

		// 定位new,显式调用T的构造函数初始化
		// new (address) type
		new(obj)T;

		return obj;
	}

	void Delete(T* obj)
	{
		// 显式调用析构函数清理对象
		obj->~T();

		// 头插
		//*(int*)obj = _freeList; // 这里不能这样用,因为x32和x64情况下,指针大小不同
		*(void**)obj = _freeList;
		_freeList = obj;

	}
private:
	char* _memory = nullptr; // 指向大块内存的指针
	void* _freeList = nullptr; // 还回来的内存的自由链表的头指针
	size_t _remainBytes = 0; // 大块内存在切分过程中剩余字节数,用于防止越界
};
  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值