IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C++项目高并发内存池_定长内存池 -> 正文阅读

[数据结构与算法]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;
}

在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:51:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:41:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码