裁剪与依赖
| 功能宏 | 能力 | 直接依赖 |
|---|
XRT_FEATURE_QUEUE | 公共结果、容量规则 | XRT_FEATURE_ATOMIC |
XRT_FEATURE_QUEUE_SPSC | 单生产者、单消费者队列 | XRT_FEATURE_QUEUE |
XRT_FEATURE_QUEUE_MPSC | 多生产者、单消费者序列槽队列 | XRT_FEATURE_QUEUE |
XRT_FEATURE_QUEUE_MPMC | 多生产者、多消费者序列槽队列 | XRT_FEATURE_QUEUE |
启用子模块时必须显式启用依赖宏;公共头会在依赖缺失时拒绝编译。SPSC、MPSC 和 MPMC 核心不依赖线程、锁、信号量或任务体系。
公共契约
xrtQueueCapacity 把非零最小容量向上取整到 2 次幂。支持范围为 1 到 XRT_QUEUE_MAX_CAPACITY;零容量报告 XERR_ARGUMENT,超过上限报告 XERR_RANGE。
xqueueresult 将并发流控与运行库错误分开:
| 结果 | 含义 |
|---|
XQUEUE_OK | 操作成功 |
XQUEUE_EMPTY | 当前没有可读元素,但仍可能继续写入 |
XQUEUE_FULL | 当前没有可写槽位 |
XQUEUE_CLOSED | 写入端已经关闭;弹出操作返回该值时队列已经排空 |
XQUEUE_ERROR | 参数、状态、内存或系统错误,详细信息由 xrtGetError 取得 |
xqueuebatchresult 同时返回状态和实际处理数量。批量操作允许部分成功,此时 Result 为 XQUEUE_OK,Count 小于请求数。请求数为零是无副作用的成功操作,不要求数组指针非空。
所有非空批量指针数组和单元素 Pop 输出都必须按指针对齐,并且不能与队列结构或内部环重叠。实现只检查本次实际访问的批量前缀;违反条件设置 XERR_ARGUMENT、返回 XQUEUE_ERROR,且不领取槽位、不移动游标、不写输出。公开结构的存储地址、容量、掩码或游标关系损坏时设置 XERR_STATE,不会把损坏的容量差用于环访问。
队列保存原始指针值,不拥有指针目标,也不限制空指针元素。空指针元素由 xqueueresult 与真正的空队列区分。
等待、期限和取消不是基础队列结果。后续等待包装层使用统一的 xwaitresult,不会把同步原语依赖反向引入队列核心。
SPSC
xspscqueue 只允许一个生产者执行入队、批量入队和关闭,只允许一个消费者执行弹出、批量弹出和排空。状态查询可以由其他线程调用。违反角色数量约束属于调用方错误,库无法在不损失热路径性能的情况下检测。
生产者通过 release 发布尾游标,消费者通过 acquire 取得元素;消费者以 release 发布头游标,生产者以 acquire 复用槽位。生产者必须在最后一次入队完成后调用 xrtSPSCQueueClose。消费者观察到关闭后会再次确认尾游标,因此不会把关闭发布前的最后一批元素遗漏为已排空。
MPSC
xmpscqueue 允许多个生产者并发执行入队和批量入队,只允许一个消费者执行弹出、批量弹出和排空。状态查询可以由其他线程调用。实现继承旧版 XRT 已验证的有界序列槽环,但用 32 位模运算代替旧版 64 位游标,避免 32 位目标上昂贵的 64 位原子操作。
每个槽位以 release 发布序号和元素,消费者以 acquire 取得;消费者释放槽位后,生产者才可在下一轮复用。容量上限为 2^30,因此序号差转换为有符号 32 位值时,即使游标跨越 UINT32_MAX 也不会混淆空槽、就绪槽和已越过槽。
MPSC 提供非阻塞的尝试式 API,但不声明形式化的 lock-free 进度保证:生产者取得尾部区间后若被长期挂起,唯一消费者必须等待该 FIFO 前缀发布。需要可等待、期限和取消的调用方,应使用后续同步/任务阶段提供的等待适配层,核心队列不会引入线程和同步原语依赖。
MPMC
xmpmcqueue 允许多个生产者并发入队,也允许多个消费者并发弹出。生产者热路径与 MPSC 共用同一份内部序列槽实现;消费者通过 CAS 领取头部的一个槽或一个连续批量区间。两套公开 API 分别表达不同角色合同,不要求调用方接触通用基类或函数指针。
MPMC 与 MPSC 使用相同的 32 位模序号、2^30 容量上限、release/acquire 发布关系和热游标隔离。x86 目标使用 64 字节隔离跨度,AArch64 与 PowerPC64 目标使用 128 字节隔离跨度;这是布局规则,不承诺等同于运行 CPU 的实际缓存行大小。它同样提供非阻塞尝试式 API,但不声明形式化的 lock-free 进度保证:已经取得头尾区间后暂停的线程可能暂时阻塞 FIFO 前缀或槽位复用。
示例
可运行范例位于 examples/containers/queue_spsc/main.c。
MPSC 的批量范例位于 examples/containers/queue_mpsc/main.c。
MPMC 的批量范例位于 examples/containers/queue_mpmc/main.c,多线程竞争由 tests/containers/test_queue_mpmc_threads.c 完整演示。
性能门禁
dev/bench/queue/bench_queue_pointer.c 测量 SPSC、MPSC、MPMC 的单元素与批量吞吐量,dev/bench/queue/bench_queue_latency.c 测量 MPSC、MPMC 的平均延迟、P50、P95、P99 与消费者公平性。两者直接编译当前 single/xrt.h,不依赖网络头或网络链接库。
Windows 与 Linux runner 位于 dev/bench/run_queue_*。历史 20260324、20260325 报告只作为旧版比较证据;XRT 2 的发布结论必须使用固定主机、编译器、矩阵和串行采样重新生成,不能把诊断用 CPU 绑定结果混入默认基线。
xqueueresult类型
队列结果把正常流控状态与真正错误分开表达。
| 值 | 语义 |
|---|
XQUEUE_ERROR | 失败 |
XQUEUE_OK | 成功 |
XQUEUE_EMPTY | 已空 |
XQUEUE_FULL | 已满 |
XQUEUE_CLOSED | 已关闭 |
typedef enum xqueueresult { XQUEUE_ERROR = -1, XQUEUE_OK = 0, XQUEUE_EMPTY = 1, XQUEUE_FULL = 2, XQUEUE_CLOSED = 3 } xqueueresult;
xqueuebatchresult类型
批量操作同时返回流控状态和实际处理数量。
| 字段 | 类型 | 语义 |
|---|
Result | xqueueresult | 结果输出 |
Count | size_t | 数量 |
typedef struct xqueuebatchresult { xqueueresult Result; size_t Count; } xqueuebatchresult;
xqueuecursor32类型
32 位游标独占一个架构隔离跨度,避免生产者和消费者伪共享。
| 字段 | 类型 | 语义 |
|---|
Position | xatomic32 | 位置 |
typedef struct xqueuecursor32 { xatomic32 Position; uint8 Reserved[XRT_QUEUE_CACHE_SPAN - sizeof( xatomic32)
xqueueslot类型
序列槽保存一个不拥有目标的指针,并用序号表达空闲和就绪代次。
| 字段 | 类型 | 语义 |
|---|
Sequence | xatomic32 | Sequence |
Item | ptr | Item |
typedef struct xqueueslot { xatomic32 Sequence; ptr Item; } xqueueslot;
xspscqueue类型
SPSC 保存指针值,只允许一个生产者和一个消费者并发操作。
| 字段 | 类型 | 语义 |
|---|
Items | ptr* | 元素数组 |
Allocation | ptr | Allocation |
Capacity | size_t | 容量 |
Mask | size_t | Mask |
Closed | xatomic32 | Closed |
Tail | xqueuecursor32 | 尾指针 |
Head | xqueuecursor32 | 头指针 |
typedef struct xspscqueue { ptr* Items; ptr Allocation; size_t Capacity; size_t Mask; xatomic32 Closed; xqueuecursor32 Tail; xqueuecursor32 Head; } xspscqueue;
xmpscqueue类型
MPSC 允许多个生产者并发写入,只允许一个消费者读取。
| 字段 | 类型 | 语义 |
|---|
Slots | xqueueslot* | Slots |
Allocation | ptr | Allocation |
Capacity | size_t | 容量 |
Mask | size_t | Mask |
Closed | xatomic32 | Closed |
Tail | xqueuecursor32 | 尾指针 |
Head | xqueuecursor32 | 头指针 |
typedef struct xmpscqueue { xqueueslot* Slots; ptr Allocation; size_t Capacity; size_t Mask; xatomic32 Closed; xqueuecursor32 Tail; xqueuecursor32 Head; } xmpscqueue;
xmpmcqueue类型
MPMC 允许多个生产者和多个消费者并发访问同一个有界序列槽环。
| 字段 | 类型 | 语义 |
|---|
Slots | xqueueslot* | Slots |
Allocation | ptr | Allocation |
Capacity | size_t | 容量 |
Mask | size_t | Mask |
Closed | xatomic32 | Closed |
Tail | xqueuecursor32 | 尾指针 |
Head | xqueuecursor32 | 头指针 |
typedef struct xmpmcqueue { xqueueslot* Slots; ptr Allocation; size_t Capacity; size_t Mask; xatomic32 Closed; xqueuecursor32 Tail; xqueuecursor32 Head; } xmpmcqueue;
xqueuedrainfn类型
排空回调接收已从队列移除的指针值。 回调类型;参数与返回语义见签名及各使用方 API 节。
typedef void(*xqueuedrainfn)(ptr pItem, ptr pContext)
xrtQueueCapacity函数
把最小容量向上取整为队列可使用的 2 次幂容量。
size_t xrtQueueCapacity(size_t iMinimum)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
iMinimum | 输入 | — | 期望最小容量 |
范例已编译验证
tour · 容量取整
xrtQueueCapacity(3u), xrtQueueCapacity(16u));
关闭、排空与重置
xrtSPSCQueueInit函数
初始化拥有内部指针环的 SPSC 队列;容量向上取整为 2 的幂。
bool xrtSPSCQueueInit(xspscqueue* pQueue, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 内嵌初始化
if ( !xrtSPSCQueueInit(&Queue, 4u) ) {
xrtSPSCQueueInitBuffer函数
在调用方提供的 2 的幂指针环上初始化 SPSC 队列。
bool xrtSPSCQueueInitBuffer(xspscqueue* pQueue, ptr* pItems, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
pItems | 输入 | 非空、2 的幂容量 | 指针环数组 |
iCapacity | 输入 | 2 的幂 | 槽数 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_VALUE — 容量不是 2 的幂
范例已编译验证
spsc · 外部存储初始化
if ( !xrtSPSCQueueInitBuffer(&Queue, Storage, 8u) ) {
xrtSPSCQueueCreate函数
创建拥有结构和内部指针环的 SPSC 队列。
xspscqueue* xrtSPSCQueueCreate(size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
| 非空 | 队列 | — |
NULL | 创建失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 堆创建
xspscqueue* pHeap = xrtSPSCQueueCreate(8u);
xrtSPSCQueueUnit函数
释放拥有的指针环,但不释放队列结构或指针目标。
void xrtSPSCQueueUnit(xspscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
spsc · 释放内部环
xrtSPSCQueueUnit(&Queue);
xrtSPSCQueueDestroy函数
释放 Create 返回的队列结构和内部指针环。
void xrtSPSCQueueDestroy(xspscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
tour · 销毁队列
xrtSPSCQueueDestroy(pHeap);
xrtSPSCQueueTryPush函数
尝试压入一个可为空的指针值。
xqueueresult xrtSPSCQueueTryPush(xspscqueue* pQueue, ptr pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输入 | 任意值 | 要压入的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值推送
if ( (xrtSPSCQueueTryPush(&Queue, (ptr)1) != XQUEUE_OK) ||
(xrtSPSCQueueTryPush(&Queue, (ptr)2) != XQUEUE_OK) ||
(xrtSPSCQueueCount(&Queue) != 2u) ) {
xrtSPSCQueuePushBatch函数
尝试批量压入连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtSPSCQueuePushBatch(xspscqueue* pQueue, ptr const* pItems, size_t iCount)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输入 | 非空数组 | 指针数组 |
iCount | 输入 | > 0 | 期望压入数量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
tour · 批量推送
Batch = xrtSPSCQueuePushBatch(&Queue, Items, 3u);
xrtSPSCQueueTryPop函数
尝试弹出一个指针值;输出必须对齐且不与队列对象或内部环重叠。
xqueueresult xrtSPSCQueueTryPop(xspscqueue* pQueue, ptr* pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输出 | 非空 | 接收弹出的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值弹出
if ( (xrtSPSCQueueTryPop(&Queue, &Value) !=
XQUEUE_OK) || ((intptr_t)Value != 1) ) {
xrtSPSCQueuePopBatch函数
尝试批量弹出连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtSPSCQueuePopBatch(xspscqueue* pQueue, ptr* pItems, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输出 | 非空数组 | 接收数组 |
iCapacity | 输入 | > 0 | 期望弹出容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
tour · 批量弹出
Batch = xrtSPSCQueuePopBatch(&Queue, Out, 4u);
xrtSPSCQueueCount函数
返回并发快照下的近似元素数量。
size_t xrtSPSCQueueCount(const xspscqueue* pQueue)
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 数量快照
(xrtSPSCQueueCount(&Queue) != 2u) ) {
xrtSPSCQueueClose函数
由唯一生产者幂等关闭写入端,并允许消费者继续排空已有元素。
void xrtSPSCQueueClose(xspscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 关闭写入端
xrtSPSCQueueClose(&Queue);
xrtSPSCQueueIsClosed函数
判断队列写入端是否已经关闭。
bool xrtSPSCQueueIsClosed(const xspscqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是已关闭 | — |
false | 不是已关闭 | — |
范例已编译验证
tour · 关闭查询
XQUEUE_CLOSED) || !xrtSPSCQueueIsClosed(&Queue) ||
xrtSPSCQueueIsDrained函数
判断队列是否已经关闭且排空。
bool xrtSPSCQueueIsDrained(const xspscqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是关闭且排空 | — |
false | 不是关闭且排空 | — |
范例已编译验证
tour · 排空查询
!xrtSPSCQueueIsDrained(&Queue) ||
xrtSPSCQueueDrain函数
排空当前可见元素;回调为空时直接丢弃指针值。
size_t xrtSPSCQueueDrain(xspscqueue* pQueue, xqueuedrainfn pDrain, ptr pContext)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
pDrain | 输入 | 允许空 | 逐值回调 |
pContext | 输入 | 任意值 | 回调上下文 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 排空
if ( (xrtSPSCQueueDrain(&Queue, exampleDrainAdd, &Sum) !=
1u) || (Sum.Count != 1u) ||
(xrtAtomic64Load(&Sum.Total, XMEMORY_RELAXED) != 7) ) {
xrtSPSCQueueReset函数
在调用方独占且队列为空时重置游标并重新开放。
bool xrtSPSCQueueReset(xspscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已重置并重新开放 | — |
false | 队列非空或状态不允许 | 不设错误 |
错误- 队列非空或未满足独占前提返回
false 且不设置错误;句柄为空 XERR_ARGUMENT
范例已编译验证
tour · 重置
if ( !xrtSPSCQueueReset(&Queue) ||
(xrtSPSCQueueTryPush(&Queue, (ptr)7) !=
XQUEUE_OK) ||
xrtSPSCQueueIsClosed(&Queue) ) {
xrtMPSCQueueInit函数
初始化拥有内部序列槽环的 MPSC 队列;容量向上取整为 2 的幂。
bool xrtMPSCQueueInit(xmpscqueue* pQueue, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 内嵌初始化
if ( !xrtMPSCQueueInit(&Queue, 8u) ||
(xrtMPSCQueueTryPush(&Queue, (ptr)11) !=
XQUEUE_OK) ) {
xrtMPSCQueueInitBuffer函数
在调用方提供的 2 的幂序列槽环上初始化 MPSC 队列。
bool xrtMPSCQueueInitBuffer(xmpscqueue* pQueue, xqueueslot* pSlots, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
pSlots | 输入 | 非空、2 的幂容量 | 序列槽环数组 |
iCapacity | 输入 | 2 的幂 | 槽数 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_VALUE — 容量不是 2 的幂
范例已编译验证
mpsc · 外部存储初始化
if ( !xrtMPSCQueueInitBuffer(&Queue, Storage, 8u) ) {
xrtMPSCQueueCreate函数
创建拥有结构和内部序列槽环的 MPSC 队列。
xmpscqueue* xrtMPSCQueueCreate(size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
| 非空 | 队列 | — |
NULL | 创建失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 堆创建
xmpscqueue* pQueue = xrtMPSCQueueCreate(64u);
xrtMPSCQueueUnit函数
释放拥有的序列槽环,但不释放队列结构或指针目标。
void xrtMPSCQueueUnit(xmpscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
mpsc · 释放内部环
xrtMPSCQueueUnit(&Queue);
xrtMPSCQueueDestroy函数
释放 Create 返回的队列结构和内部序列槽环。
void xrtMPSCQueueDestroy(xmpscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
tour · 销毁队列
xrtMPSCQueueDestroy(pQueue);
xrtMPSCQueueTryPush函数
尝试压入一个可为空的指针值。
xqueueresult xrtMPSCQueueTryPush(xmpscqueue* pQueue, ptr pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输入 | 任意值 | 要压入的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值推送
while ( xrtMPSCQueueTryPush(pJob->pQueue, Value) ==
XQUEUE_FULL ) {
xrtMPSCQueuePushBatch函数
尝试批量压入连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtMPSCQueuePushBatch(xmpscqueue* pQueue, ptr const* pItems, size_t iCount)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输入 | 非空数组 | 指针数组 |
iCount | 输入 | > 0 | 期望压入数量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
mpsc · 批量推送
if ( xrtMPSCQueuePushBatch(&Queue, pFirstBatch, 2u).Count != 2u ) {
xrtMPSCQueueTryPop函数
尝试弹出一个指针值;输出必须对齐且不与队列对象或内部环重叠。
xqueueresult xrtMPSCQueueTryPop(xmpscqueue* pQueue, ptr* pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输出 | 非空 | 接收弹出的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值弹出
while ( xrtMPSCQueueTryPop(pQueue, &Value) ==
XQUEUE_OK ) {
xrtMPSCQueuePopBatch函数
尝试批量弹出连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtMPSCQueuePopBatch(xmpscqueue* pQueue, ptr* pItems, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输出 | 非空数组 | 接收数组 |
iCapacity | 输入 | > 0 | 期望弹出容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
mpsc · 批量弹出
Batch = xrtMPSCQueuePopBatch(&Queue, pOutput, 4u);
xrtMPSCQueueCount函数
返回并发快照下的近似元素数量。
size_t xrtMPSCQueueCount(const xmpscqueue* pQueue)
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 数量快照
(xrtMPSCQueueCount(pQueue) != 0u) ) {
xrtMPSCQueueClose函数
由唯一生产者幂等关闭写入端,并允许消费者继续排空已有元素。
void xrtMPSCQueueClose(xmpscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 关闭写入端
xrtMPSCQueueClose(&Queue);
xrtMPSCQueueIsClosed函数
判断队列写入端是否已经关闭。
bool xrtMPSCQueueIsClosed(const xmpscqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是已关闭 | — |
false | 不是已关闭 | — |
范例已编译验证
tour · 关闭查询
if ( !xrtMPSCQueueIsClosed(pQueue) ||
!xrtMPSCQueueIsDrained(pQueue) ||
!xrtMPSCQueueReset(pQueue) ) {
xrtMPSCQueueIsDrained函数
判断队列是否已经关闭且排空。
bool xrtMPSCQueueIsDrained(const xmpscqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是关闭且排空 | — |
false | 不是关闭且排空 | — |
范例已编译验证
tour · 排空查询
!xrtMPSCQueueIsDrained(pQueue) ||
xrtMPSCQueueDrain函数
排空当前可见元素;回调为空时直接丢弃指针值。
size_t xrtMPSCQueueDrain(xmpscqueue* pQueue, xqueuedrainfn pDrain, ptr pContext)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
pDrain | 输入 | 允许空 | 逐值回调 |
pContext | 输入 | 任意值 | 回调上下文 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 排空
(void)xrtMPSCQueueDrain(&Queue, exampleDrainAdd, &Sum);
xrtMPSCQueueReset函数
在调用方独占且队列为空时重置游标并重新开放。
bool xrtMPSCQueueReset(xmpscqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已重置并重新开放 | — |
false | 队列非空或状态不允许 | 不设错误 |
错误- 队列非空或未满足独占前提返回
false 且不设置错误;句柄为空 XERR_ARGUMENT
范例已编译验证
tour · 重置
if ( (Sum.Count != 1u) || !xrtMPSCQueueReset(&Queue) ) {
关闭与生命周期
xrtMPMCQueueInit函数
初始化拥有内部序列槽环的 MPMC 队列;容量向上取整为 2 的幂。
bool xrtMPMCQueueInit(xmpmcqueue* pQueue, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 内嵌初始化
if ( !xrtMPMCQueueInit(&Queue, 8u) ||
(xrtMPMCQueueTryPush(&Queue, (ptr)21) !=
XQUEUE_OK) ||
(xrtMPMCQueueTryPush(&Queue, (ptr)22) !=
XQUEUE_OK) ) {
xrtMPMCQueueInitBuffer函数
在调用方提供的 2 的幂序列槽环上初始化 MPMC 队列。
bool xrtMPMCQueueInitBuffer(xmpmcqueue* pQueue, xqueueslot* pSlots, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输出 | 非空 | 接收队列 |
pSlots | 输入 | 非空、2 的幂容量 | 序列槽环数组 |
iCapacity | 输入 | 2 的幂 | 槽数 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已初始化 | — |
false | 失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_VALUE — 容量不是 2 的幂
范例已编译验证
mpmc · 外部存储初始化
if ( !xrtMPMCQueueInitBuffer(&Queue, Storage, 8u) ) {
xrtMPMCQueueCreate函数
创建拥有结构和内部序列槽环的 MPMC 队列。
xmpmcqueue* xrtMPMCQueueCreate(size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
iCapacity | 输入 | > 0 | 期望容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
| 非空 | 队列 | — |
NULL | 创建失败 | 见错误 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠XERR_RANGE — 容量取整或分配尺寸溢出XERR_MEMORY — 内部环分配失败
范例已编译验证
tour · 堆创建
xmpmcqueue* pQueue = xrtMPMCQueueCreate(64u);
xrtMPMCQueueUnit函数
释放拥有的序列槽环,但不释放队列结构或指针目标。
void xrtMPMCQueueUnit(xmpmcqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
mpmc · 释放内部环
xrtMPMCQueueUnit(&Queue);
xrtMPMCQueueDestroy函数
释放 Create 返回的队列结构和内部序列槽环。
void xrtMPMCQueueDestroy(xmpmcqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 允许空 | 空 = 空操作 |
范例已编译验证
tour · 销毁队列
xrtMPMCQueueDestroy(NULL); /* 空指针是空操作 */
xrtMPMCQueueTryPush函数
尝试压入一个可为空的指针值。
xqueueresult xrtMPMCQueueTryPush(xmpmcqueue* pQueue, ptr pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输入 | 任意值 | 要压入的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值推送
while ( xrtMPMCQueueTryPush(pJob->pQueue, Value) ==
XQUEUE_FULL ) {
xrtMPMCQueuePushBatch函数
尝试批量压入连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtMPMCQueuePushBatch(xmpmcqueue* pQueue, ptr const* pItems, size_t iCount)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输入 | 非空数组 | 指针数组 |
iCount | 输入 | > 0 | 期望压入数量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
mpmc · 批量推送
if ( xrtMPMCQueuePushBatch(&Queue, pFirstBatch, 2u).Count != 2u ) {
xrtMPMCQueueTryPop函数
尝试弹出一个指针值;输出必须对齐且不与队列对象或内部环重叠。
xqueueresult xrtMPMCQueueTryPop(xmpmcqueue* pQueue, ptr* pItem)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItem | 输出 | 非空 | 接收弹出的指针 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
XQUEUE_OK | 操作成功 | — |
XQUEUE_FULL / XQUEUE_EMPTY | 队列满 / 空 | 不设错误 |
XQUEUE_CLOSED | 写入端已关闭(推送),或已关闭且排空(弹出) | 不设错误 |
XQUEUE_ERROR | 参数非法或内部状态破坏 | XERR_ARGUMENT / XERR_STATE |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)
范例已编译验证
tour · 单值弹出
if ( xrtMPMCQueueTryPop(pJob->pQueue, &Value) ==
XQUEUE_OK ) {
xrtMPMCQueuePopBatch函数
尝试批量弹出连续指针值;数组必须对齐且不与队列对象或内部环重叠。
xqueuebatchresult xrtMPMCQueuePopBatch(xmpmcqueue* pQueue, ptr* pItems, size_t iCapacity)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入 | 非空 | 目标队列 |
pItems | 输出 | 非空数组 | 接收数组 |
iCapacity | 输入 | > 0 | 期望弹出容量 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
.Result | 同单值口径(OK / FULL / EMPTY / CLOSED / ERROR) | — |
.Count | 实际完成数量,允许部分完成 | — |
错误XERR_ARGUMENT — 队列指针为空XERR_STATE — 内部游标破坏(已损坏的队列对象)XERR_ARGUMENT — 数组为空或与队列对象重叠
范例已编译验证
mpmc · 批量弹出
Batch = xrtMPMCQueuePopBatch(&Queue, pOutput, 4u);
xrtMPMCQueueCount函数
返回并发快照下的近似元素数量。
size_t xrtMPMCQueueCount(const xmpmcqueue* pQueue)
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 数量快照
(xrtMPMCQueueCount(pJob->pQueue) == 0u) ) {
xrtMPMCQueueClose函数
由唯一生产者幂等关闭写入端,并允许消费者继续排空已有元素。
void xrtMPMCQueueClose(xmpmcqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 关闭写入端
xrtMPMCQueueClose(pQueue);
xrtMPMCQueueIsClosed函数
判断队列写入端是否已经关闭。
bool xrtMPMCQueueIsClosed(const xmpmcqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是已关闭 | — |
false | 不是已关闭 | — |
范例已编译验证
tour · 关闭查询
else if ( xrtMPMCQueueIsClosed(pJob->pQueue) &&
(xrtMPMCQueueCount(pJob->pQueue) == 0u) ) {
xrtMPMCQueueIsDrained函数
判断队列是否已经关闭且排空。
bool xrtMPMCQueueIsDrained(const xmpmcqueue* pQueue)
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 是关闭且排空 | — |
false | 不是关闭且排空 | — |
范例已编译验证
tour · 排空查询
!xrtMPMCQueueIsDrained(pQueue) ) {
xrtMPMCQueueDrain函数
排空当前可见元素;回调为空时直接丢弃指针值。
size_t xrtMPMCQueueDrain(xmpmcqueue* pQueue, xqueuedrainfn pDrain, ptr pContext)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
pDrain | 输入 | 允许空 | 逐值回调 |
pContext | 输入 | 任意值 | 回调上下文 |
错误XERR_ARGUMENT — 指针为空、容量为零或缓冲与队列对象重叠
范例已编译验证
tour · 排空
if ( (xrtMPMCQueueDrain(&Queue, exampleDrainAdd, &Sum) !=
2u) || (Sum.Count != 2u) ||
(xrtAtomic64Load(&Sum.Total, XMEMORY_RELAXED) != 43) ||
!xrtMPMCQueueReset(&Queue) ) {
xrtMPMCQueueReset函数
在调用方独占且队列为空时重置游标并重新开放。
bool xrtMPMCQueueReset(xmpmcqueue* pQueue)
参数
| 参数 | 方向 | 约束 | 说明 |
|---|
pQueue | 输入/输出 | 非空 | 目标队列 |
返回值| 返回 | 含义 | 失败时状态 |
|---|
true | 已重置并重新开放 | — |
false | 队列非空或状态不允许 | 不设错误 |
错误- 队列非空或未满足独占前提返回
false 且不设置错误;句柄为空 XERR_ARGUMENT
范例已编译验证
tour · 重置
!xrtMPMCQueueReset(&Queue) ) {
常量索引常量
以下常量在本页所属头文件中定义,语义见公共头注释。
| 常量 | 说明 |
| XQUEUE_CLOSED | 见头文件注释 |
| XQUEUE_EMPTY | 见头文件注释 |
| XQUEUE_ERROR | 见头文件注释 |
| XQUEUE_FULL | 见头文件注释 |
| XQUEUE_OK | 见头文件注释 |
| XRT_QUEUE_CACHE_SPAN | 见头文件注释 |
| XRT_QUEUE_MAX_CAPACITY | 见头文件注释 |