分层模型

内存池由浅入深分为三层:

层类型适用场景
单页xpoolpage精确控制一个 1 到 256 槽固定对象页,或搭建更高层分配器
固定池xpool同一种结构或节点的长期高频分配,按约 64 KiB 目标自适应页容量并自动跨页增长
变长池xmempool同一生命周期域内的多尺寸内存,小块池化,大块独立登记

旧版 MemUnit 的 256 槽默认布局、空闲槽复用、满页边界和显式标记回收被保留;重复实现多页固定块管理的 BSMM 与 FSMemPool 合并为 xpool。多页固定池不再把每种对象都机械放大为 256 个槽:小对象仍保持 256 槽吞吐,大对象按目标页字节数降低槽数。xmempool 继续采用 16 字节尺寸类和默认 1024 字节分界,但删除了未参与当前分配路径的二叉树、LUT 和对象前 4 字节头。

三个层次都可独立裁剪。XRT_FEATURE_POOL 依赖 XRT_FEATURE_POOL_PAGE,XRT_FEATURE_MEMORY_POOL 依赖前两层。

旧版资产复用

这三层实现逐项审计了旧版 memunit.h、bsmm.h、mempool_fs.h、mempool.h 及其测试、范例和中英文文档。

保留并加强的资产:

  • MemUnit 的 256 槽默认容量、释放槽复用、满页失败和“释放标记/释放未标记”两种回收语义。
  • FSMemPool 的跨页增长、满页与可用页迁移、空页缓存策略。
  • MemPool 的小块分级、可配置分界和大块回退路径。
  • 旧测试中的尺寸边界、256 槽边界、跨页增长、复用与 GC 场景,已改为无需人工查看输出的自动断言。

新增的自适应页容量解决了旧实现的大对象放大问题:显式单页仍可选择旧版 256 槽布局,通用多页池则不会为一个 8 KiB 对象立即申请约 2 MiB,也不会为一个 1 MiB 对象立即申请约 256 MiB。上层 AVLTree 等稳定地址容器直接复用这一能力,无需重复实现大对象旁路。

明确淘汰的实现:

  • 用户内存前方的 4 字节管理头。新实现用外置位图、页地址索引和大块哈希登记,避免读取未知指针前方内存,并完整支持显式对齐。
  • BSMM 和 FSMemPool 两套重叠的多页管理器。其有效能力统一进入 xpool,不保留重复 API 和实现。
  • 旧变长池未参与最终热路径的树字段与重复 LUT 状态。新尺寸类可直接通过除法定位。
  • 打印内部字段、依赖人工判断结果的旧测试形式。有效场景保留,测试方式升级为自动失败。

范例与回归

完整范例位于:

  • examples/memory/pool_page/main.c
  • examples/memory/pool/main.c
  • examples/memory/memory_pool/main.c

三个裁剪层可分别执行:

构建脚本同时运行普通实现、范例和对应单头文件测试。

XRT_POOL_PAGE_CAPACITY常量

单页支持的最大槽数,也是快捷单页入口的默认槽数,值为 256。

XRT_POOL_PAGE_BYTES_DEFAULT常量

多页固定池的默认目标页字节数,值为 65536。自动布局使用 clamp(65536 / stride, 1, 256) 选择每页槽数,其中 stride 是对齐后的实际槽步长。 因此小对象保持 256 槽,大对象不会仅因进入固定池就预留 256 倍对象大小的首批内存。 当单个槽已经超过 64 KiB 时,一页只包含一个槽。

XRT_POOL_ALIGNMENT_DEFAULT常量

默认对象对齐,值为 16。

XRT_MEMPOOL_CLASS_STEP常量

变长池的小块尺寸类步长,值为 16。

XRT_MEMPOOL_CUTOFF_DEFAULT常量

变长池默认小块分界,值为 1024。

xpoolerror类型

内存池错误代码在 xrt.pool 域内稳定。

值语义
XPOOL_ERROR_INVALID_POINTER无效POINTER
XPOOL_ERROR_NOT_ALLOCATED失败
XPOOL_ERROR_PAGE_FULLPAGE已满
XPOOL_ERROR_INVALID_ALIGNMENT无效ALIGNMENT
XPOOL_ERROR_INVALID_SIZE无效尺寸
XPOOL_ERROR_INDEX_OUT_OF_RANGE索引OUTOF范围越界
XPOOL_ERROR_VISIT_ACTIVE失败
XPOOL_ERROR_INVALID_CAPACITY容量参数非法
typedef enum xpoolerror { XPOOL_ERROR_INVALID_POINTER = 1, XPOOL_ERROR_NOT_ALLOCATED, XPOOL_ERROR_PAGE_FULL, XPOOL_ERROR_INVALID_ALIGNMENT, XPOOL_ERROR_INVALID_SIZE, XPOOL_ERROR_INDEX_OUT_OF_RANGE, XPOOL_ERROR_VISIT_ACTIVE, XPOOL_ERROR_INVALID_CAPACITY } xpoolerror;

xmempoolbucket类型

变长池的 16 字节尺寸类内部桶结构(不透明,仅实现内部使用)。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xmempoolbucket xmempoolbucket;

xmempoollarge类型

超过池化上限的独立大块登记结构(不透明,仅实现内部使用)。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xmempoollarge xmempoollarge;
单页池

xpoolpage类型

Allocation 和 Memory 分别是底层分配地址与对齐后的槽区;ItemSize、Stride、Alignment、MemorySize 和 Capacity 描述布局。Used 与 Marked 是外置位图,因而不占用户对象空间。FreeList、LiveCount、NextIndex 和 FreeCount 管理分配状态。四个链指针、Parent 和 Flags 供上层固定池维护页关系,不得由调用方修改。

xpoolpageinfo类型

ItemSize 是用户对象大小,Stride 是实际槽步长,Alignment 是对齐;LiveCount、FreeCount 和 Capacity 分别表示活动槽、可直接复用槽和总槽数。

xrtPoolPageInit函数

使用默认 16 字节对齐初始化一个空的 256 槽页。

bool xrtPoolPageInit(xpoolpage* pPage, size_t iItemSize)

参数

参数方向约束说明
pPage输出非空接收页
iItemSize输入> 0每槽字节数
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 默认初始化

		if ( !xrtPoolPageInit(&DefaultPage, sizeof(uint64)) ) {

xrtPoolPageInitAligned函数

使用指定的二次幂对齐初始化一个空的 256 槽页。

bool xrtPoolPageInitAligned(xpoolpage* pPage, size_t iItemSize, size_t iAlignment)

参数

参数方向约束说明
pPage输出非空接收页
iItemSize输入> 0每槽字节数
iAlignment输入二次幂槽对齐
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 对齐初始化

	if ( !xrtPoolPageInitAligned(&tPage, sizeof(int), 32) ) {

xrtPoolPageInitLayout函数

使用显式对齐和槽数初始化一个空页。

bool xrtPoolPageInitLayout(xpoolpage* pPage, size_t iItemSize, size_t iAlignment, size_t iCapacity)

参数

参数方向约束说明
pPage输出非空接收页
iItemSize输入> 0每槽字节数
iAlignment输入二次幂槽对齐
iCapacity输入> 0槽数
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 完整布局初始化

		if ( !xrtPoolPageInitLayout(&LayoutPage, sizeof(uint64),
				32u, 8u) ||
			(LayoutPage.Capacity != 8u) ) {

xrtPoolPageCreate函数

创建一个使用默认 16 字节对齐的 256 槽页。

xpoolpage* xrtPoolPageCreate(size_t iItemSize)

参数

参数方向约束说明
iItemSize输入> 0每槽字节数
返回值
返回含义失败时状态
非空页(含槽内存)—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 创建页

	pCreated = xrtPoolPageCreate(sizeof(uint64));

xrtPoolPageCreateAligned函数

创建一个使用指定对齐的 256 槽页。

xpoolpage* xrtPoolPageCreateAligned(size_t iItemSize, size_t iAlignment)

参数

参数方向约束说明
iItemSize输入> 0每槽字节数
iAlignment输入二次幂槽对齐
返回值
返回含义失败时状态
非空页(含槽内存)—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 创建页(对齐)

		pAligned = xrtPoolPageCreateAligned(sizeof(uint64), 32u);

xrtPoolPageCreateLayout函数

创建一个使用显式对齐和槽数的页。

xpoolpage* xrtPoolPageCreateLayout(size_t iItemSize, size_t iAlignment, size_t iCapacity)

参数

参数方向约束说明
iItemSize输入> 0每槽字节数
iAlignment输入二次幂槽对齐
iCapacity输入> 0槽数
返回值
返回含义失败时状态
非空页(含槽内存)—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

page · 创建页(完整布局)

	pCompact = xrtPoolPageCreateLayout(8192, 64, 4);

xrtPoolPageUnit函数

释放页持有的槽内存,但不释放页结构。

void xrtPoolPageUnit(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入允许空空 = 空操作
返回值
返回含义失败时状态
无槽内存已释放—
错误
  • 无 — 释放不失败

范例已编译验证

page · 释放槽内存

		xrtPoolPageUnit(&tPage);

xrtPoolPageDestroy函数

释放页持有的全部资源和页结构。

void xrtPoolPageDestroy(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入允许空空 = 空操作
返回值
返回含义失败时状态
无页已释放—
错误
  • 无 — 释放不失败

范例已编译验证

page · 销毁页

		xrtPoolPageDestroy(pCompact);

xrtPoolPageAlloc函数

分配一个未初始化槽,页满时返回空指针并设置 XERR_AGAIN。

ptr xrtPoolPageAlloc(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入非空目标页
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_AGAIN — 页已满,无空闲槽

范例已编译验证

page · 分配槽

	pDrop = (int*)xrtPoolPageAlloc(&tPage);

xrtPoolPageCalloc函数

分配并清零一个槽,页满时返回空指针并设置 XERR_AGAIN。

ptr xrtPoolPageCalloc(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入非空目标页
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_AGAIN — 页已满,无空闲槽

范例已编译验证

page · 清零分配槽

	pKeep = (int*)xrtPoolPageCalloc(&tPage);

xrtPoolPageFree函数

安全释放一个活动槽,非法、跨页或重复释放均返回 false。

bool xrtPoolPageFree(xpoolpage* pPage, ptr pMemory)

参数

参数方向约束说明
pPage输入非空目标页
pMemory输入本页活动槽要释放的槽
返回值
返回含义失败时状态
true已释放—
false非法、跨页或重复释放XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

page · 释放槽

	if ( (pValue == NULL) || !xrtPoolPageFree(&tPage, pValue) ) {

xrtPoolPageFreeAt函数

按槽索引释放活动对象。

bool xrtPoolPageFreeAt(xpoolpage* pPage, size_t iIndex)

参数

参数方向约束说明
pPage输入非空目标页
iIndex输入< 槽数槽索引
返回值
返回含义失败时状态
true已释放—
false空闲或越界不设错
错误
  • 空闲槽或索引越界返回 false 且不设置错误;空句柄 XERR_ARGUMENT

范例已编译验证

page · 按索引释放

		!xrtPoolPageFreeAt(&tPage, iIndex)

xrtPoolPageGet函数

返回指定索引处的活动对象,空闲或越界时返回空指针。

ptr xrtPoolPageGet(const xpoolpage* pPage, size_t iIndex)

参数

参数方向约束说明
pPage输入非空目标页
iIndex输入< 槽数槽索引
返回值
返回含义失败时状态
非空活动对象—
NULL空闲或越界不设错
错误
  • 空闲槽或索引越界返回 NULL 且不设置错误;空句柄 XERR_ARGUMENT

范例已编译验证

page · 按索引取对象

		(xrtPoolPageGet(&tPage, iIndex) != pKeep)

xrtPoolPageIndex函数

获取活动对象的槽索引。

bool xrtPoolPageIndex(const xpoolpage* pPage, const void* pMemory, size_t* pIndex)

参数

参数方向约束说明
pPage输入非空目标页
pMemory输入本页活动槽目标对象
pIndex输出非空接收槽索引
返回值
返回含义失败时状态
true已写出索引—
false非本页活动对象XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

page · 对象索引

		!xrtPoolPageIndex(&tPage, pKeep, &iIndex) ||

xrtPoolPageOwns函数

判断指针当前是否属于该页的活动槽。

bool xrtPoolPageOwns(const xpoolpage* pPage, const void* pMemory)

参数

参数方向约束说明
pPage输入非空目标页
pMemory输入任意待判断指针
返回值
返回含义失败时状态
true是本页活动槽—
false不是本页活动槽不设错误
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

page · 归属判断

		!xrtPoolPageOwns(&tPage, pKeep) ||

xrtPoolPageMark函数

将一个活动槽标记为本轮可达对象。

bool xrtPoolPageMark(xpoolpage* pPage, ptr pMemory)

参数

参数方向约束说明
pPage输入/输出非空目标页
pMemory输入本页活动槽目标对象
返回值
返回含义失败时状态
true已标记—
false非本页/池活动对象XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

page · 标记

	if ( !xrtPoolPageMark(&tPage, pKeep) || (xrtPoolPageSweep(&tPage) != 1) ) {

xrtPoolPageSweep函数

释放未标记槽,并清除幸存槽的标记。

size_t xrtPoolPageSweep(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入/输出非空目标页
返回值
返回含义失败时状态
>= 0释放的未标记槽数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

page · 清扫

	if ( !xrtPoolPageMark(&tPage, pKeep) || (xrtPoolPageSweep(&tPage) != 1) ) {

xrtPoolPageFreeMarked函数

释放已标记槽,适合显式批量选择释放。

size_t xrtPoolPageFreeMarked(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入/输出非空目标页
返回值
返回含义失败时状态
>= 0释放的已标记槽数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

page · 释放已标记

	if ( !xrtPoolPageMark(&tPage, pKeep) || (xrtPoolPageFreeMarked(&tPage) != 1) ) {

xrtPoolPageReset函数

将页内全部槽恢复为空闲状态并返回释放的活动槽数。

size_t xrtPoolPageReset(xpoolpage* pPage)

参数

参数方向约束说明
pPage输入/输出非空目标页
返回值
返回含义失败时状态
>= 0释放的活动槽数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

page · 全部重置

		(xrtPoolPageReset(&tPage) != 2)

xrtPoolPageGetInfo函数

获取单页当前状态。

void xrtPoolPageGetInfo(const xpoolpage* pPage, xpoolpageinfo* pInfo)

参数

参数方向约束说明
pPage输入非空目标页
pInfo输出非空接收状态快照
返回值
返回含义失败时状态
无快照已写出—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

page · 状态查询

	xrtPoolPageGetInfo(&tPage, &tInfo);
固定对象池

xpool类型

Pages 是全部页链,Available 是可分配页链,Index 是按槽区地址排序的安全查找索引。ItemSize、Alignment、PageCapacity、PageCount、EmptyPages、LiveCount、PeakCount、AllocCount、FreeCount 和 RetainEmpty 提供布局、统计与保留策略。IndexCapacity 和 Flags 是内部状态。

xpoolinfo类型

包含对象大小、步长、对齐、每页槽数、页数、空页数、实时/峰值对象数、总容量和累计分配/释放次数。理论容量无法用 size_t 表示时,Capacity 饱和为 SIZE_MAX。

xpoolvisitor类型

签名为 bool visitor(ptr object, size_t index, ptr userData)。index 是本次遍历从零开始的连续序号,不是可持久化句柄。返回 false 提前停止。

xrtPoolInit函数

使用默认 16 字节对齐初始化固定对象池。

bool xrtPoolInit(xpool* pPool, size_t iItemSize)

参数

参数方向约束说明
pPool输出非空接收池
iItemSize输入> 0每对象字节数
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 默认初始化

		if ( !xrtPoolInit(&DefaultPool, sizeof(examplejob)) ) {

xrtPoolInitAligned函数

使用指定的二次幂对齐初始化固定对象池。

bool xrtPoolInitAligned(xpool* pPool, size_t iItemSize, size_t iAlignment)

参数

参数方向约束说明
pPool输出非空接收池
iItemSize输入> 0每对象字节数
iAlignment输入二次幂对象对齐
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 对齐初始化

	if ( !xrtPoolInitAligned(&tPool, sizeof(examplejob), 32) ) {

xrtPoolInitLayout函数

使用显式对齐和每页槽数初始化固定对象池。

bool xrtPoolInitLayout(xpool* pPool, size_t iItemSize, size_t iAlignment, size_t iPageCapacity)

参数

参数方向约束说明
pPool输出非空接收池
iItemSize输入> 0每对象字节数
iAlignment输入二次幂对象对齐
iPageCapacity输入> 0每页槽数
返回值
返回含义失败时状态
true已初始化—
false布局参数非法见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 完整布局初始化

		if ( !xrtPoolInitLayout(&LayoutPool, sizeof(examplejob),
				32u, 64u) ||
			(LayoutPool.PageCapacity != 64u) ) {

xrtPoolCreate函数

创建使用默认 16 字节对齐的固定对象池。

xpool* xrtPoolCreate(size_t iItemSize)

参数

参数方向约束说明
iItemSize输入> 0每对象字节数
返回值
返回含义失败时状态
非空池—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 创建池

	pCompact = xrtPoolCreate(8192);

xrtPoolCreateAligned函数

创建使用指定对齐的固定对象池。

xpool* xrtPoolCreateAligned(size_t iItemSize, size_t iAlignment)

参数

参数方向约束说明
iItemSize输入> 0每对象字节数
iAlignment输入二次幂对象对齐
返回值
返回含义失败时状态
非空池—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 创建池(对齐)

		pAligned = xrtPoolCreateAligned(sizeof(examplejob), 32u);

xrtPoolCreateLayout函数

创建使用显式对齐和每页槽数的固定对象池。

xpool* xrtPoolCreateLayout(size_t iItemSize, size_t iAlignment, size_t iPageCapacity)

参数

参数方向约束说明
iItemSize输入> 0每对象字节数
iAlignment输入二次幂对象对齐
iPageCapacity输入> 0每页槽数
返回值
返回含义失败时状态
非空池—
NULL创建失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — 项大小或容量为零、溢出
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 创建池(完整布局)

	pCreated = xrtPoolCreateLayout(sizeof(examplejob), 32, 128);

xrtPoolUnit函数

释放池持有的全部页,但不释放池结构。

void xrtPoolUnit(xpool* pPool)

参数

参数方向约束说明
pPool输入允许空空 = 空操作
返回值
返回含义失败时状态
无全部页已释放—
错误
  • 无 — 释放不失败

范例已编译验证

pool · 释放页

			xrtPoolUnit(&tPool);

xrtPoolDestroy函数

释放池持有的全部资源和池结构。

void xrtPoolDestroy(xpool* pPool)

参数

参数方向约束说明
pPool输入允许空空 = 空操作
返回值
返回含义失败时状态
无池已释放—
错误
  • 无 — 释放不失败

范例已编译验证

pool · 销毁池

		xrtPoolDestroy(pCompact);

xrtPoolAlloc函数

分配一个未初始化对象;池需要新页时可能分配内存。

ptr xrtPoolAlloc(xpool* pPool)

参数

参数方向约束说明
pPool输入非空目标池
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 分配对象

	pReused = (examplejob*)xrtPoolAlloc(&tPool);

xrtPoolCalloc函数

分配并清零一个对象;池需要新页时可能分配内存。

ptr xrtPoolCalloc(xpool* pPool)

参数

参数方向约束说明
pPool输入非空目标池
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

pool · 清零分配对象

		arrJob[i] = (examplejob*)xrtPoolCalloc(&tPool);

xrtPoolFree函数

安全释放活动对象,非法、跨池或重复释放均返回 false。

bool xrtPoolFree(xpool* pPool, ptr pObject)

参数

参数方向约束说明
pPool输入非空目标池
pObject输入本池活动对象要释放的对象
返回值
返回含义失败时状态
true已释放—
false非法、跨页或重复释放XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

pool · 释放对象

	if ( !xrtPoolFree(&tPool, pReleased) ) {

xrtPoolOwns函数

判断指针当前是否属于该池的活动对象。

bool xrtPoolOwns(const xpool* pPool, const void* pObject)

参数

参数方向约束说明
pPool输入非空目标池
pObject输入任意待判断指针
返回值
返回含义失败时状态
true是本池活动对象—
false不是本池活动对象不设错误
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

pool · 归属判断

	if ( !xrtPoolOwns(&tPool, pReused) ) {

xrtPoolMark函数

标记一个活动对象为本轮可达。

bool xrtPoolMark(xpool* pPool, ptr pObject)

参数

参数方向约束说明
pPool输入/输出非空目标池
pObject输入本池活动对象目标对象
返回值
返回含义失败时状态
true已标记—
false非本页/池活动对象XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

pool · 标记

	if ( !xrtPoolMark(&tPool, arrJob[0]) || (xrtPoolSweep(&tPool) != 299) ) {

xrtPoolSweep函数

释放全部未标记对象,并清除幸存对象标记。

size_t xrtPoolSweep(xpool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的未标记对象数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 清扫

	if ( !xrtPoolMark(&tPool, arrJob[0]) || (xrtPoolSweep(&tPool) != 299) ) {

xrtPoolFreeMarked函数

释放全部已标记对象。

size_t xrtPoolFreeMarked(xpool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的已标记对象数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 释放已标记

	if ( !xrtPoolMark(&tPool, arrJob[0]) || (xrtPoolFreeMarked(&tPool) != 1) ) {

xrtPoolReset函数

释放全部活动对象,并按保留策略回收空页。

size_t xrtPoolReset(xpool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的活动对象数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 全部重置

	if ( xrtPoolReset(&tPool) != 300 ) {

xrtPoolTrim函数

回收多余空页,返回真正释放的页数。

size_t xrtPoolTrim(xpool* pPool, size_t iRetainEmpty)

参数

参数方向约束说明
pPool输入/输出非空目标池
iRetainEmpty输入—保留的空页数
返回值
返回含义失败时状态
>= 0释放的页数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 裁剪空页

	if ( xrtPoolTrim(&tPool, 0) == 0 ) {

xrtPoolSetRetain函数

设置自动保留的空页数,并立即执行一次裁剪。

void xrtPoolSetRetain(xpool* pPool, size_t iRetainEmpty)

参数

参数方向约束说明
pPool输入/输出非空目标池
iRetainEmpty输入—保留的空页数
返回值
返回含义失败时状态
无已设置并裁剪—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 设置保留策略

	xrtPoolSetRetain(&tPool, 2);

xrtPoolGet函数

获取固定对象池当前状态。

void xrtPoolGet(const xpool* pPool, xpoolinfo* pInfo)

参数

参数方向约束说明
pPool输入非空目标池
pInfo输出非空接收状态快照
返回值
返回含义失败时状态
无快照已写出—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 状态查询

	xrtPoolGet(&tPool, &tInfo);

xrtPoolVisit函数

访问活动对象;遍历期间只允许查询和标记,不得改变池的分配集合。

size_t xrtPoolVisit(xpool* pPool, xpoolvisitor pVisitor, ptr pUserData)

参数

参数方向约束说明
pPool输入非空目标池
pVisitor输入非空访问回调
pUserData输入任意值回调数据
返回值
返回含义失败时状态
>= 0实际访问的对象数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

pool · 遍历对象

	if ( xrtPoolVisit(&tPool, exampleVisitJob, &iVisited) != 300 ) {
变长内存池

xmempool类型

Buckets 是 16 字节尺寸类数组,Pages 是所有小块页的有序查找索引,Large 是独立大块哈希登记表。Cutoff、ClassCount、PageCount、LargeCount、LiveCount、PeakCount、LiveBytes、PeakBytes、AllocCount 和 FreeCount 是配置与统计。其余容量、删除计数和 Flags 是内部状态。

xmempoolinfo类型

包含分界、尺寸类步长/数量、页数、小块/大块数量、实时/峰值块数、实时/峰值可用字节及累计操作次数。小块字节按尺寸类可用大小统计,不是原请求大小。

xmempoolvisitor类型

签名为 bool visitor(ptr memory, size_t size, size_t alignment, ptr userData)。size 是 xrtMemPoolSize 可查询的安全可用大小,返回 false 提前停止。

xrtMemPoolInit函数

初始化变长池,iCutoff 为零时使用默认值 1024。

bool xrtMemPoolInit(xmempool* pPool, size_t iCutoff)

参数

参数方向约束说明
pPool输出非空接收池
iCutoff输入0 = 1024池化小块上限
返回值
返回含义失败时状态
true已初始化—
false参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 初始化

	if ( !xrtMemPoolInit(&tPool, 128) ) {

xrtMemPoolCreate函数

创建变长池,iCutoff 为零时使用默认值 1024。

xmempool* xrtMemPoolCreate(size_t iCutoff)

参数

参数方向约束说明
iCutoff输入0 = 1024池化小块上限
返回值
返回含义失败时状态
非空变长池—
NULL创建失败XERR_ARGUMENT / XERR_MEMORY
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

mempool · 创建池

	pCreated = xrtMemPoolCreate(0);

xrtMemPoolUnit函数

释放池持有的全部资源,但不释放池结构;不调用块内对象析构器。

void xrtMemPoolUnit(xmempool* pPool)

参数

参数方向约束说明
pPool输入允许空空 = 空操作
返回值
返回含义失败时状态
无全部资源已释放—
错误
  • 无 — 释放不失败

范例已编译验证

mempool · 释放资源

		xrtMemPoolUnit(&tPool);

xrtMemPoolDestroy函数

释放池持有的全部资源和池结构;不调用块内对象析构器。

void xrtMemPoolDestroy(xmempool* pPool)

参数

参数方向约束说明
pPool输入允许空空 = 空操作
返回值
返回含义失败时状态
无池已释放—
错误
  • 无 — 释放不失败

范例已编译验证

mempool · 销毁池

	xrtMemPoolDestroy(pCreated);

xrtMemPoolAlloc函数

按 16 字节对齐分配内存,大小为零时仍返回至少一个可用字节。

ptr xrtMemPoolAlloc(xmempool* pPool, size_t iSize)

参数

参数方向约束说明
pPool输入非空目标池
iSize输入—请求字节数
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

mempool · 分配块

	pPacket = (bytes)xrtMemPoolAlloc(&tPool, 4096);

xrtMemPoolCalloc函数

分配 iCount * iSize 字节并清零;乘法溢出时失败,总大小为零时仍分配至少一个字节。

ptr xrtMemPoolCalloc(xmempool* pPool, size_t iCount, size_t iSize)

参数

参数方向约束说明
pPool输入非空目标池
iCount输入—元素数量
iSize输入—每元素字节数
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_RANGE — iCount * iSize 乘法溢出
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

mempool · 清零分配块

	sText = (char*)xrtMemPoolCalloc(&tPool, 1, 24);

xrtMemPoolAllocAligned函数

按指定二次幂对齐分配,零大小仍有效,超过 16 字节对齐时走独立大块。

ptr xrtMemPoolAllocAligned(xmempool* pPool, size_t iSize, size_t iAlignment)

参数

参数方向约束说明
pPool输入非空目标池
iSize输入—请求字节数
iAlignment输入二次幂对齐
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_VALUE — 对齐不是二次幂
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

mempool · 对齐分配块

	pAligned = (bytes)xrtMemPoolAllocAligned(&tPool, 7, 64);

xrtMemPoolRealloc函数

调整池内块大小并保留已有内容,大小为零时释放。

ptr xrtMemPoolRealloc(xmempool* pPool, ptr pMemory, size_t iSize)

参数

参数方向约束说明
pPool输入非空目标池
pMemory输入本池活动块或空要调整的块
iSize输入—新字节数,0 = 释放
返回值
返回含义失败时状态
非空槽内存,至少按 16 字节对齐—
NULL失败见错误

(pMemory 为空且大小非零时等价分配)

错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法
  • XERR_MEMORY — 槽内存分配失败

范例已编译验证

mempool · 调整块大小

	sText = (char*)xrtMemPoolRealloc(&tPool, sText, 80);

xrtMemPoolFree函数

安全释放池内活动块,非法、跨池或重复释放均返回 false。

bool xrtMemPoolFree(xmempool* pPool, ptr pMemory)

参数

参数方向约束说明
pPool输入非空目标池
pMemory输入本池活动块要释放的块
返回值
返回含义失败时状态
true已释放—
false非法、跨页或重复释放XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

mempool · 释放块

		!xrtMemPoolFree(&tPool, sText)

xrtMemPoolSize函数

返回活动块可安全使用的字节数,不属于该池时返回零。

size_t xrtMemPoolSize(const xmempool* pPool, const void* pMemory)

参数

参数方向约束说明
pPool输入非空目标池
pMemory输入任意待查询指针
返回值
返回含义失败时状态
>= 0可用字节数;0 = 不属于本池—
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

mempool · 块大小查询

		(xrtMemPoolSize(&tPool, sText) < 80) ||

xrtMemPoolOwns函数

判断指针当前是否属于该池的活动块。

bool xrtMemPoolOwns(const xmempool* pPool, const void* pMemory)

参数

参数方向约束说明
pPool输入非空目标池
pMemory输入任意待判断指针
返回值
返回含义失败时状态
true是本池活动块—
false不是本池活动块不设错误
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

mempool · 归属判断

		!xrtMemPoolOwns(&tPool, sText) ||

xrtMemPoolMark函数

标记一个活动块为本轮可达。

bool xrtMemPoolMark(xmempool* pPool, ptr pMemory)

参数

参数方向约束说明
pPool输入/输出非空目标池
pMemory输入本池活动块目标块
返回值
返回含义失败时状态
true已标记—
false非本页/池活动对象XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 重复释放、指针不属于本对象或内部状态非法

范例已编译验证

mempool · 标记

		!xrtMemPoolMark(&tPool, sText) ||

xrtMemPoolSweep函数

释放全部未标记块,并清除幸存块标记。

size_t xrtMemPoolSweep(xmempool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的未标记块数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 清扫

		(xrtMemPoolSweep(&tPool) != 1)

xrtMemPoolFreeMarked函数

释放全部已标记块。

size_t xrtMemPoolFreeMarked(xmempool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的已标记块数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 释放已标记

		(xrtMemPoolFreeMarked(&tPool) != 1) ||

xrtMemPoolReset函数

释放全部活动块,并保留每个尺寸类的一个空页。

size_t xrtMemPoolReset(xmempool* pPool)

参数

参数方向约束说明
pPool输入/输出非空目标池
返回值
返回含义失败时状态
>= 0释放的活动块数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 全部重置

		(xrtMemPoolReset(&tPool) != 2)

xrtMemPoolTrim函数

将每个尺寸类的空页裁剪到指定数量。

size_t xrtMemPoolTrim(xmempool* pPool, size_t iRetainEmptyPerClass)

参数

参数方向约束说明
pPool输入/输出非空目标池
iRetainEmptyPerClass输入—每尺寸类保留空页数
返回值
返回含义失败时状态
>= 0释放的页数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 裁剪空页

	(void)xrtMemPoolTrim(&tPool, 0);

xrtMemPoolGet函数

获取变长池当前状态。

void xrtMemPoolGet(const xmempool* pPool, xmempoolinfo* pInfo)

参数

参数方向约束说明
pPool输入非空目标池
pInfo输出非空接收状态快照
返回值
返回含义失败时状态
无快照已写出—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 状态查询

	xrtMemPoolGet(&tPool, &tInfo);

xrtMemPoolVisit函数

访问活动块;遍历期间只允许查询和标记,不得改变池的分配集合。

size_t xrtMemPoolVisit(xmempool* pPool, xmempoolvisitor pVisitor, ptr pUserData)

参数

参数方向约束说明
pPool输入非空目标池
pVisitor输入非空访问回调
pUserData输入任意值回调数据
返回值
返回含义失败时状态
>= 0实际访问的块数—
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

mempool · 遍历块

	if ( xrtMemPoolVisit(&tPool, exampleVisitMemory, &iVisited) != 3 ) {

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XPOOL_ERROR_INDEX_OUT_OF_RANGE见头文件注释
XPOOL_ERROR_INVALID_ALIGNMENT见头文件注释
XPOOL_ERROR_INVALID_CAPACITY见头文件注释
XPOOL_ERROR_INVALID_POINTER见头文件注释
XPOOL_ERROR_INVALID_SIZE见头文件注释
XPOOL_ERROR_NOT_ALLOCATED见头文件注释
XPOOL_ERROR_PAGE_FULL见头文件注释
XPOOL_ERROR_VISIT_ACTIVE见头文件注释