C++项目高并发内存池_定长内存池

思路

首先定义ObjectPool类,类成员(char*)_memory提前向系统申请内存。
在这里插入图片描述

如果有申请内存的行为,则_memory指针向后移动,将分出的内存给要申请的地方。

如果有归还内存的地方时,选择使用(void*)freeList链表将所有要归还内存链接起来
在这里插入图片描述
但是要注意,归还内存内部保存的是下一个归还节点的地址,所以这个归还节点在32位下要大于4字节,64位下大于8字节。
这个链表最后指向nullptr
在链表内部的空间块中保存指向下一个内存块的地址
eg:使用obj指针标记要回收地址的起始位置。
(void**)obj解引用=下一块回收空间的地址。
因为不知道是32位还是64位,无法判断一个指针的大小(不同平台指针大小不同,但常规指针类型解引用大小相同),所以这里强转为二级指针类型再解引用(得到指针类型)就可以保证无论在几位机器,一定可以开辟足够的空间大小存下一块内存的地址

注意:如果归还的内存块大小不够保存一个指针,我们在new的之后就保证一定可以存放一个指针的大小

当这块内存被申请完毕的时候,要继续向系统申请内存,所以还需要一个成员变量_overage来记录剩余空间的大小
当剩余大小不够一个对象大小时就需要重新开辟空间

这个大块内存不需要进行内存释放,因为这个内存伴随进程生命周期,当进程退出时,释放内存。

C++代码

#pragma once

#include<iostream>

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

template<class T>//定长内存池
class ObjectPool {
private:
	char* _memory;//指向大块内存的指针
	//返回的内存用链式结构管理
	void* _freeList;
	size_t _overage;//大块内存剩余空间大小
public:
	ObjectPool() :_memory(nullptr), _freeList(nullptr),_overage(0) {}

	T* New() {
		T* obj = nullptr;
		if (_freeList != nullptr) {
			//优先把归还的内存重复利用
			//链表头删
			void* next = *((void**)_freeList);
			obj = (T*)_freeList;
			_freeList = next;
		}
		else
		{
			if (_overage < sizeof(T)) {
				_overage = 100 * 1024;
				_memory = (char*)malloc(_overage);
				if (_memory == nullptr) {
					throw std::bad_alloc();
				}
			}
			obj = (T*)_memory;
			size_t SizeT = sizeof(T) > sizeof(void*) ? sizeof(T) : sizeof(void*);
			_memory += SizeT;
			_overage -= SizeT;
		}
		//调用定位new进行空间初始化
		new(obj)T;
		return obj;
	}

	void Delete(T* obj) {
		obj->~T();//显示调用析构函数,清理对象
		//头插
		*(void**)obj = _freeList;
		_freeList = obj;
	}
};

Release与直接new开空间测试

#include"ObjectPool.h"

#include<vector>
#include<time.h>

using namespace std;

struct TreeNode 
{ 
	int _val; 
	TreeNode* _left;  
	TreeNode* _right;   
	TreeNode() :_val(0), _left(nullptr), _right(nullptr) {}
};

int main()
{
	size_t N = 1000000;
	vector<TreeNode*>vet;
	vet.resize(N);
	size_t begin = clock();
	for (int i = 0; i < vet.size(); i++) {
		vet[i]=new TreeNode;
	}
	for (int i = 0; i < vet.size(); i++) {
		delete vet[i];
	}

	size_t end = clock();
	cout << "new TreeNode Time:" << end - begin << endl;

	ObjectPool<TreeNode>pool;
	size_t begin2 = clock();
	for (int i = 0; i < vet.size(); i++) {
		vet[i]=pool.New();
	}
	for (int i = 0; i < vet.size(); i++) {
		pool.Delete(vet[i]);
	}
	size_t end2 = clock();
	cout << "ObjectPool New Time:" << end2 - begin2 << endl;
	return 0;
}

在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NUC_Dodamce

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

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

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

打赏作者

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

抵扣说明:

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

余额充值