高并发内存池|定长内存池的设计

二、定长内存池的设计

设计一个定长的内存池,这个内存池的定长在于,当剩余空间使用完毕后,总是开辟相同长度的新空间来使用。我们会使用到一个指针来切割划分大空间为小空间。大空间是内存池向系统申请的内存大小,而小空间是程序向该内存池申请的内存大小。由于程序向内存池申请存放空间的类型不同,这个小空间的大小也由需要存放的类型决定大小。

FixedPool1

实际上指针只有一个, _freeList 后面的空间理论上是连起来的, _freeList 在被申请空间后更新,相当于链表的头插头删。

#include <iostream>
#include <vector>
#ifdef _WIN32
#include <Windows.h>
#endif
//从堆上按页申请空间
inline static void* SystemAlloc(size_t page)
{
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, page << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#endif
#ifdef __linux__
	size_t size = page << 13;
	void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

#endif
	if (ptr == nullptr)
	{
		throw std::bad_alloc();
	}
	return ptr;
}

template<class T>
class FixedPool
{
	T* New()
	{
		T* object = nullptr;
		//优先使用还回来的空间
		if (_freeList)
		{
			void* next = *((void**)_freeList);
			object = (T*)_freeList;
			_freeList = next;
		}

		//如果大空间不足
		if (_restBytes < sizeof(T))
		{
			_restBytes = 128 * 1024;	//一次申请128Kb的空间
			_memory = (char*)SystemAlloc(_restBytes >> 13);	//128Kb右移13位相当于16页
			if (_memory == nullptr)
			{
				throw std::bad_alloc();
			}
		}

		//从申请的大空间中截一块出来
		object = (T*)_memory;
		size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
		_memory += objSize;
		_restBytes -= objSize;

		//定位new,显示调用T的构造函数
		new(obj)T;

		return obj;
	}

	void Delete(T* obj)
	{
		obj->~T();
		*(void**)obj = _freeList;
		_freeList = obj;//把空间还回来
	}
private:
	char* _memory = nullptr;	//char类型为1字节大小方便申请任意大小的内存
	size_t _restBytes = 0;	//记录大内存在切分后的剩余比特数
	void* _freeList = nullptr;
};

*(void**) 的强制类型转换是在兼容 32 位和 64 位,使其不会因为指针大小不同而程序出错,也不用为了兼容 32 位和 64 位使用条件编译。

size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T); 这行,要求开的空间必须比指针大,因为我们会用归还回来的空间存放,_freeList 来指向下一块空间,如果 T 小于指针的大小,就有可能存不进 _freeList

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

laimaxgg

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

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

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

打赏作者

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

抵扣说明:

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

余额充值