模块契约Thread

所有权

  • xrtThreadCreate() 返回一个拥有引用,运行线程另外持有一个内部引用。
  • 调用方可以立即 xrtThreadDestroy(),让线程在没有外部句柄时安全运行到结束。
  • 跨所有权边界共享对象时调用 xrtThreadRef();每个拥有引用最终释放一次。
  • xrtThreadCurrent() 返回借用对象,只在线程入口执行期间有效,不得释放或保存到入口之外。
  • 等待者必须在整个等待期间持有对象引用;多个等待者可以并发等待同一对象。

线程安全与错误

状态、退出码、停止请求和等待都可并发访问。引用计数只保护已经合法持有的引用, 不能让一个线程在另一线程释放最后一个外部引用的同时从裸指针获取新引用。 API 返回失败时,当前线程可通过结构化错误接口读取 xrt.thread 错误域信息。

可运行示例见 examples/concurrency/thread/main.c;生命周期、detach、多等待者、 自等待和 OOM 边界见 tests/concurrency/test_thread.c 与 tests/concurrency/test_thread_oom.c。

原生线程

引用计数线程对象、等待与协作停止。

线程局部键

动态原生线程局部存储。

模块契约Once 一次初始化

裁剪宏:XRT_FEATURE_ONCE直接依赖:core 模块(无独立裁剪宏)头文件:<xrt/thread.h> 或 <xrt.h>

原生线程

线程局部键

所有权

xonce 为固定存储对象,初始化开始后不可复制或移动;线程键为引用计数对象(Create 引用 1,Ref 递增,Destroy 递减);KeySet/KeyTake 转移槽内值的所有权。

类型

xthread 是不透明对象。线程入口接收创建时的 pData,返回稳定的 32 位退出码。

状态只表达“运行”和“完成”。协作停止请求不是第三种执行状态。

函数

函数说明
xrtThreadCreate(pProc, pData, iStackSize)创建并立即启动线程;栈大小为 0 时使用平台默认值。失败返回 NULL。
xrtThreadRef(pThread)增加拥有引用并返回原指针;无效对象返回 NULL。
xrtThreadDestroy(pThread)释放一个拥有引用;传入 NULL 无操作,不等待也不强制停止线程。
xrtThreadWait(pThread)无限等待线程执行体和 XRT 线程上下文清理完成,返回 xwaitresult。
xrtThreadWaitFor(pThread, iTimeout)最多等待相对毫秒数。0 是非阻塞状态检查。
xrtThreadWaitFor(pThread, iDeadline)等待线程执行体和 XRT 线程上下文清理完成到单调时钟 deadline。
xrtThreadStop(pThread)幂等地发布协作停止请求。
xrtThreadStopRequested(pThread)查询指定线程是否收到停止请求。
xrtThreadStopping()在线程入口内查询当前线程的停止请求;外部线程返回 false。
xrtThreadState(pThread)返回线程状态快照。
xrtThreadExitCode(pThread)线程完成后返回退出码;仍运行时返回 0 并设置状态错误。
xrtThreadId(pThread)返回对象记录的进程内非零线程标识。
xrtThreadCurrentId()返回调用线程的进程内非零线程标识,外部创建的线程也可使用。
xrtThreadCurrent()返回当前 XRT 线程的借用对象;外部线程返回 NULL。
xrtThreadYield()主动让出当前处理器时间片。

xrtThreadWait()、xrtThreadWaitFor() 和 xrtThreadWaitFor() 可以重复调用, 超时不会改变对象状态,也不会消费后续等待机会。线程等待自己会返回 XWAIT_ERROR 并设置状态错误。成功返回时,线程入口已经返回,线程键、协程及当前错误等 XRT 线程上下文已经清理,内部运行引用也已经释放。

线程标识只用于同一进程生命周期内的相等性比较,不是可持久化编号。线程结束后, 操作系统可以把相同标识分配给后续线程。xrtThreadExitCode() 在线程仍运行时返回零并 设置 XERR_STATE,因此调用方应先等待完成,不能仅凭返回的零判断真实退出码。

协作停止

库不提供强制终止、挂起或恢复线程。这些操作会破坏资源清理顺序,且跨平台语义不一致。

API 参考

以下各节复用自 once.md(两者映射同一 include/xrt/thread.h),按线程视角重组。

Once 一次初始化

可失败、可重试的并发一次初始化。

示例

完整示例位于 examples/concurrency/once/main.c。

示例

完整示例位于 examples/concurrency/thread_key/main.c。

API 参考

以下各节复用自 once.md(两者映射同一 include/xrt/thread.h),以线程局部键为主线重组。

Once 一次初始化

线程模块共享的并发一次初始化原语。

xonce类型

Once 对象的字段保持不透明,只能使用 XRT_ONCE_INIT 或全零初始化。

字段类型语义
Alignmentuint64对齐(二次幂)
typedef union xonce { uint64 Alignment; uint8 Storage[XRT_ONCE_STORAGE_SIZE]; } xonce;

xthreadstate类型

线程只有运行和完成两种可观测状态,停止请求不伪装成执行状态。

值语义
XTHREAD_RUNNINGXTHREAD运行中
XTHREAD_FINISHED已结束
typedef enum xthreadstate { XTHREAD_RUNNING = 0, XTHREAD_FINISHED = 1 } xthreadstate;

xthreadkey类型

动态键按原生线程隔离,同一线程上的 Fiber 和协程共享其值。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xthreadkey xthreadkey;

xthread类型

原生线程对象对外保持不透明,并使用引用计数管理生命周期。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xthread xthread;

xonceproc类型

初始化过程返回 true 时永久完成,返回 false 时允许后续调用重试。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef bool(*xonceproc)(ptr pData)

xthreadkeyproc类型

非空线程局部值在线程退出、显式清理或被替换时交给析构过程。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef void(*xthreadkeyproc)(ptr pValue)

xthreadproc类型

线程入口返回稳定的 32 位退出码。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef int32(*xthreadproc)(ptr pData)
Once 一次初始化

xrtOnce函数

并发执行一次初始化;成功后所有调用返回 true,失败后状态回到未完成并允许后续调用重试。

bool xrtOnce(xonce* pOnce, xonceproc pProc, ptr pData)

参数

参数方向约束说明
pOnce输入/输出非空、已初始化一次初始化对象
pProc输入非空初始化过程,返回 false = 本次失败
pData输入任意值过程数据
返回值
返回含义失败时状态
true初始化已完成(本次或此前)—
false本次初始化失败,可重试过程保留的错误或 XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 同一线程从初始化过程递归进入相同对象(自死锁保护)
  • 过程失败时应自行设置线程错误;未设置时不额外构造

范例已编译验证

once · 一次初始化

	if ( !xrtOnce(&tOnce, initializeConfig, &iConfig) ) {

xrtThreadCreate函数

创建并立即启动原生线程;栈大小为零时使用平台默认值。对象使用引用计数,初始引用包含调用方一份和运行自持一份。

xthread* xrtThreadCreate(xthreadproc pProc, ptr pData, size_t iStackSize)

参数

参数方向约束说明
pProc输入非空线程执行体
pData输入任意值执行体数据
iStackSize输入0 = 平台默认栈字节数
返回值
返回含义失败时状态
非空线程对象(引用 1 + 运行自持)—
NULL创建失败XERR_ARGUMENT 等
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_MEMORY — 对象分配失败
  • xrt.thread 域错误 — 平台线程创建失败,保留系统码

范例已编译验证

thread_tour · 创建并启动

	pThread = xrtThreadCreate(exampleWorker, NULL, 0u);

xrtThreadRef函数

增加线程对象引用并返回原指针。

xthread* xrtThreadRef(xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
非空原指针,引用 +1—
NULL参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

thread_tour · 共享引用

	pRef = xrtThreadRef(pThread);

xrtThreadDestroy函数

释放线程对象引用;运行线程自持引用,因此允许用它安全分离线程。

void xrtThreadDestroy(xthread* pThread)

参数

参数方向约束说明
pThread输入允许空空 = 空操作
返回值
返回含义失败时状态
无引用 -1;最后一个引用在运行结束后释放—
错误
  • 无 — 释放不失败

范例已编译验证

thread_tour · 释放引用

	xrtThreadDestroy(pRef);  /* Ref 那份 */

xrtThreadWait函数

等待线程执行体和 XRT 线程上下文清理完成;允许多个线程同时等待同一个对象。

xwaitresult xrtThreadWait(xthread* pThread)

参数

参数方向约束说明
pThread输入非空、非自身目标线程
返回值
返回含义失败时状态
XWAIT_OK线程执行体和上下文清理完成—
XWAIT_TIMEOUT相对期限或截止时间先到达不设错误
XWAIT_ERROR参数非法或等待自身线程XERR_ARGUMENT / XERR_STATE
错误
  • XERR_ARGUMENT — pThread 为空
  • XERR_STATE — 等待调用方所在的同一线程(自等待)

范例已编译验证

thread_tour · 无限等待

	if ( (void)xrtThreadWait(pStop), false ) {

xrtThreadWaitFor函数

在相对毫秒数内等待线程执行体和 XRT 线程上下文清理完成。

xwaitresult xrtThreadWaitFor(xthread* pThread, int64 iTimeout)

参数

参数方向约束说明
pThread输入非空、非自身目标线程
iTimeout输入—相对等待毫秒数
返回值
返回含义失败时状态
XWAIT_OK线程执行体和上下文清理完成—
XWAIT_TIMEOUT相对期限或截止时间先到达不设错误
XWAIT_ERROR参数非法或等待自身线程XERR_ARGUMENT / XERR_STATE
错误
  • XERR_ARGUMENT — pThread 为空
  • XERR_STATE — 等待调用方所在的同一线程(自等待)

范例已编译验证

thread_tour · 限时等待

		(xrtThreadWaitFor(pThread, 1000u) == XWAIT_OK) ) {

xrtThreadStop函数

幂等地请求线程协作停止,不会强制终止执行。

bool xrtThreadStop(xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
true请求已记录(重复请求同样成功)—
false参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

thread_tour · 请求停止

	if ( !xrtThreadStop(pStop) ) {

xrtThreadStopRequested函数

判断指定线程是否收到停止请求。

bool xrtThreadStopRequested(const xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
true是收到请求—
false不是收到请求空句柄返回 false,不设错
错误
  • 无 — 纯原子查询,不设置错误

范例已编译验证

thread_tour · 停止查询

				xrtThreadStopRequested(pJob->pSelf);

xrtThreadStopping函数

判断当前 XRT 线程是否收到停止请求。

bool xrtThreadStopping()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
true收到停止请求—
false未收到停止请求不设错误
错误
  • 无 — 纯原子查询,不设置错误

范例已编译验证

thread_tour · 自身停止查询

		if ( xrtThreadStopping() ) {

xrtThreadState函数

返回线程状态快照;只有运行和完成两种可观测状态,停止请求不伪装成执行状态。

xthreadstate xrtThreadState(const xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
XTHREAD_RUNNING执行体尚未结束—
XTHREAD_FINISHED执行体已结束参数非法时返回 XTHREAD_FINISHED
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

thread_tour · 状态快照

		(xrtThreadState(pThread) != XTHREAD_FINISHED) ||

xrtThreadExitCode函数

返回完成线程的退出码;线程仍运行或参数无效时返回零并设置错误。

int32 xrtThreadExitCode(const xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
退出码执行体返回值—
0线程仍在运行或参数非法XERR_ARGUMENT / XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 线程仍在运行

范例已编译验证

thread_tour · 退出码

		(xrtThreadExitCode(pThread) != 42) ||

xrtThreadId函数

返回线程对象在进程内稳定的非零平台标识;线程结束后该标识可能被平台复用。

uint64 xrtThreadId(const xthread* pThread)

参数

参数方向约束说明
pThread输入非空目标线程
返回值
返回含义失败时状态
非零平台线程标识—
0参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或参数非法

范例已编译验证

thread_tour · 线程标识

		(xrtThreadId(pThread) == 0u) ) {

xrtThreadCurrentId函数

返回当前线程在进程内稳定的非零平台标识,外部创建的线程同样可用。

uint64 xrtThreadCurrentId()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
非零当前线程平台标识—
错误
  • 无 — 纯查询,不设置错误

范例已编译验证

thread · 当前线程标识

		(unsigned long long)xrtThreadCurrentId());

xrtThreadCurrent函数

返回当前 XRT 创建线程的借用对象;外部线程返回空指针。

xthread* xrtThreadCurrent()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
非空当前线程对象借用,不增加引用—
NULL外部线程不设错误
错误
  • 无错误 — 外部线程返回 NULL 且不设置错误

范例已编译验证

thread_tour · 当前线程对象

			pJob->bCurrentInside = xrtThreadCurrent() != NULL;

xrtThreadYield函数

主动让出当前线程的处理器时间片。

void xrtThreadYield()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
无已让出—
错误
  • 无 — 让出不失败

范例已编译验证

thread_tour · 让出时间片

		xrtThreadYield();

xrtThreadKeyCreate函数

创建动态原生线程局部键;析构过程可以为空。

xthreadkey* xrtThreadKeyCreate(xthreadkeyproc pDestroy)

参数

参数方向约束说明
pDestroy输入允许空线程退出时的值析构过程
返回值
返回含义失败时状态
非空键(引用 1)—
NULL创建失败XERR_MEMORY 等
错误
  • XERR_MEMORY — 键对象分配失败
  • xrt.thread 域错误 — 平台 TLS 槽分配失败,保留系统码

范例已编译验证

thread_tour · 创建键

	g_pKey = xrtThreadKeyCreate(NULL);

xrtThreadKeyDestroy函数

关闭键;其他线程不得再主动访问,已有线程槽会在退出时延迟释放。

bool xrtThreadKeyDestroy(xthreadkey* pKey)

参数

参数方向约束说明
pKey输入非空、未关闭目标键
返回值
返回含义失败时状态
true已关闭—
false参数非法或已关闭XERR_ARGUMENT / XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 键已经关闭

范例已编译验证

thread_tour · 关闭键

	xrtThreadKeyDestroy(g_pKey);

xrtThreadKeyGet函数

返回当前线程的借用值;当前线程尚未设置时返回空指针。

ptr xrtThreadKeyGet(const xthreadkey* pKey)

参数

参数方向约束说明
pKey输入非空、未关闭目标键
返回值
返回含义失败时状态
非空当前线程的值借用—
NULL尚未设置键已关闭时 XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 键已经关闭

范例已编译验证

thread_tour · 读取值

			(xrtThreadKeyGet(g_pKey) == NULL);

xrtThreadKeySet函数

转移新值的所有权;成功替换后析构旧值,空值等价于清除。

bool xrtThreadKeySet(xthreadkey* pKey, ptr pValue)

参数

参数方向约束说明
pKey输入非空、未关闭目标键
pValue输入任意值新值,所有权转移
返回值
返回含义失败时状态
true已替换并析构旧值—
false失败,新值仍归调用方XERR_ARGUMENT / XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 键已经关闭或线程槽扩展失败

范例已编译验证

thread_tour · 设置值

	if ( xrtThreadKeySet(g_pKey, &g_Sentinel) ) {

xrtThreadKeyTake函数

取走当前线程的值但不执行析构;返回值所有权交给调用方。

ptr xrtThreadKeyTake(xthreadkey* pKey)

参数

参数方向约束说明
pKey输入非空、未关闭目标键
返回值
返回含义失败时状态
非空取走的值,所有权归调用方—
NULL尚未设置键已关闭时 XERR_STATE
错误
  • XERR_ARGUMENT — 指针为空或参数非法
  • XERR_STATE — 键已经关闭

范例已编译验证

thread_tour · 取走值

		ptr pTaken = xrtThreadKeyTake(g_pKey);

xrtThreadKeysClear函数

析构并清除当前原生线程的全部动态键值;XRT 创建的线程退出时自动调用。

bool xrtThreadKeysClear()

参数

参数方向约束说明
无参数———
返回值
返回含义失败时状态
true当前线程全部键值已析构清除—
false当前线程无 XRT 上下文XERR_STATE
错误
  • XERR_STATE — 外部线程尚未建立 XRT 线程上下文

范例已编译验证

thread_tour · 清空全部键值

	xrtThreadKeysClear();

XRT_ONCE_INIT常量

静态和自动对象的初始化值。XRT_ONCE_STORAGE_SIZE 表示公开不透明存储的字节数,不应依赖其内部布局。

补充参考 · 契约见公共头注释

xrtThreadStateTry函数

契约注释见公共头文件。

XRT_API bool xrtThreadStateTry(const xthread* pThread, xthreadstate* pState)

常量索引常量

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

常量说明
XRT_ONCE_STORAGE_SIZE见头文件注释
XTHREAD_FINISHED见头文件注释
XTHREAD_RUNNING见头文件注释