00.基础——简单定长内存池

        定长内存池的原理是预先向操作系统申请一大段堆区空间并进行管理,在接下来的程序中,如果需要使用堆区空间,则就从先前开辟的空间中分,而不再直接向操作系统申请,以减少程序调用操作系统接口的次数,提高运行效率。

        定长内存池有多种实现方式,这里采用T来对内存进行分块,T时用户传给内存池模板的模板参数,由memory指针管理内存池从操作系统处直接申请来的空间,称为初始资源指针;由freelist指针管理用户还回来的内存块,称为回收队列指针。

简要过程如图所示:

        值得注意的是,既然是实现内存池这种轮子功能,自然内存池本身不宜再使用new和malloc来向操作系统申请空间,在windows系统中可采用VirtualAlloc系统接口,Linux系统中可采用sbrk和mmap系统接口。

调用系统接口申请空间的函数:

#include <iostream>
#if _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#include <sys/mman.h>
#endif // _WIN32


using std::cout;
using std::endl;
using std::bad_alloc;

inline static void* systemalloc(size_t kpage)
{
	void* ptr = nullptr;
#ifdef _WIN32
	ptr = VirtualAlloc(NULL, kpage * 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
	if (kpage <= 32)//申请空间小于32页,采用sbrk接口直接扩大堆区尾指针,并将扩大的空间指针返回
	{
		ptr = sbrk(kpage * 4096);
	}
	else
	{
		ptr= mmap(NULL, kpage*4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);//申请空间大于32页,则采用mmap接口,由操作系统在空闲堆区中选择一块合适的空间返回
	}
#endif // _WIN32
	if (ptr == NULL)
	{
		throw bad_alloc();
	}
	else
		return ptr;
}

        另外,不要忘了使用定位new和手动调用析构函数来手动初始化和清理对象资源,因为在从内存池中申请来的空间定义对象,是不会调用构造函数和析构函数的(使用new运算符会自动调用,是因为new封装了调用对象构造函数和析构函数的功能)。

程序主体:

template <class T>
class ObjectPool
{
public:
	ObjectPool():Tsize(sizeof(T))
	{}
	T* New()
	{	
		T* ptr = nullptr;
		if (freelist)
		{
			ptr = (T*)freelist;
			freelist = *(void**)freelist;
		}
		else
		{
			if (leftbytes < Tsize)
			{	
				memory = (char*)systemalloc(Number_pages);//一次开辟Number_pages页,默认为10页,1页4096B
				leftbytes = Number_pages * 4096;
			}
			ptr =(T*) memory;
			size_t objectsize = Tsize >= sizeof(void*) ? Tsize : sizeof(void*);
			memory += objectsize;
			leftbytes -= objectsize;
		}
		new(ptr)T;//定位new调用T的默认构造函数
		return ptr;
	}

	void Delete(T*obj)
	{	
		obj->~T();//调用析构函数
		*(void**)obj = freelist;
		freelist =(void*) obj;
	}
private:
	char* memory = nullptr;
	int leftbytes = 0;
	void* freelist = nullptr;
	size_t Tsize;
};

通关TestObjectPool比较直接采用new运算符和使用定长内存池申请空间的速度:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值