高并发内存池(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 _WIN32
	void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
	// linux下brk mmap等
#endif

	if (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里面去切,如果没有多余的,就去找系统申请大块内存

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值