【高并发内存池】第五篇:申请内存过程调通

一. 申请内存流程梳理

在这里插入图片描述

二. 申请内存完整代码

在这里插入图片描述

1. Common.h

该头文件中包含公共的数据结构、方法、常量等。

#pragma once

#include <mutex>
#include <thread>
#include <iostream>
#include <assert.h>
#include <algorithm>

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

static const size_t NPAGES = 129;			// PageCache可申请的最大页数
static const size_t PAGE_SHIFT = 13;		// 通过移位运算计算页号和页的起始地址
static const size_t NFREELIST = 208;        // 小块定长内存自由链表桶的数量
static const size_t MAX_BYTES = 256 * 1024; // ThreadCache可申请的最大内存空间

// 条件编译不同平台、系统的页号类型
#ifdef _WIN64
	typedef unsigned long long PAGE_ID;
#elif _WIN32
	typedef size_t PAGE_ID;
#else 
	//Linux
#endif

// 条件编译不同系统的系统头文件
#ifdef _WIN32
	#include <windows.h>
#else
	// Linux
#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;
}


// 返回传入空间的头4个或8个字节内容的引用
static inline void*& NextObj(void* obj)
{
   
   
	assert(obj);

	return *(void**)obj;
}

// 管理切分好的小块定长内存的自由链表
class FreeList
{
   
   
public:
	// 头插一个小块定长内存
	void PushFront(void* obj)
	{
   
   
		assert(obj);

		NextObj(obj) = _freeList;
		_freeList = obj;
		++_size;
	}
	// 头删一个小块定长内存
	void* PopFront()
	{
   
   
		assert(!Empty());

		void* obj = _freeList;
		_freeList = NextObj(obj);
		--_size;

		return obj;
	}

	// 头插批量小块定长内存
	void PushRangeFront(void* start, void* end, size_t n)
	{
   
   
		assert(start);
		assert(end);
		assert(n > 0);

		NextObj(end) = _freeList;
		_freeList = start;
		_size += n;
	}

	// 判断自由链表是否为空
	bool Empty()
	{
   
   
		return _size == 0;
	}

	// 获取该链表像中心缓存申请内存时的慢启动调节值
	size_t GetAdjustSize()
	{
   
   
		return adjustSize;
	}

private:
	size_t _size = 0;		   // 小块定长内存的数数量
	size_t adjustSize = 1;     // 向中心缓存申请内存的慢启动调节值
	void* _freeList = nullptr; // 存储小块定长内存的自由链表
};

// 计算传入对象大小和小块定长内存的对齐映射规则
class SizeClass
{
   
   
	// 整体控制在最多10%左右的内碎片浪费

	// [1,128]				    8byte对齐	     freelists[0,16)
	// [128+1,1024]			    16byte对齐	     freelists[16,72)
	// [1024+1,8*1024]		  	128byte对齐	     freelists[72,128)
	// [8*1024+1,64*1024]	  	1024byte对齐     freelists[128,184)
	// [64*1024+1,256*1024]		8*1024byte对齐   freelists[184,208)

public:
	// 计算对齐后得到的定长块大小
	static inline size_t RoundUp(size_t bytes)
	{
   
   
		if (bytes <= 128)
		{
   
   
			return _RoundUp(bytes, 8);
		}
		else if (bytes <= 1024)
		{
   
   
			return _RoundUp(bytes, 16);
		}
		else if (bytes <= 8 * 1024)
		{
   
   
			return _RoundUp(bytes, 128);
		}
		else if (bytes <= 64 * 1024)
		{
   
   
			return _RoundUp(bytes, 1024);
		}
		else if (bytes <= 256 * 1024)
		{
   
   
			return _RoundUp(bytes, 8 * 1024);
		}
		else
		{
   
   
			assert("ThreadCache over 256k\n");
			return -1;
		}
	}

	// 计算映射到哪一个自由链表桶
	
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值