aardio 文档

协作式取消

import thread.cancellation;

取消等待是让等待者在收到取消请求后返回,而不是终止持锁者、强杀线程或关闭正在等待的句柄。取消已经开始的工作,则需要业务代码在合适的位置检查并清理资源。

本库只提供一次性取消源、可序列化描述符和只读观察者。不提供 reset、回调注册、Job 管理或事务回滚。

快速上手:取消 mutex 等待

import thread.cancellation;
import process.mutex;

var source = thread.cancellation();
var observer = thread.cancellation.open(source.token);
var mutex = process.mutex();

// 示例模拟请求已取消;实际可由另一个线程或进程请求。
source.cancel();
var acquired,status,code = mutex.wait(5000,observer);
if(acquired){
    // 包括 status == "abandoned":也已取得所有权。
    // 业务异常路径同样必须释放;close 可兜底本对象记录的次数。
    mutex.release();
}
else print(status); // cancelled

mutex.close();
observer.close();
source.close();

mutex.wait / waitOne 的可选参数

mutex.wait(timeout, cancelEvent) 是阻塞等待,不处理窗口消息。

mutex.waitOne(timeout, cancelEvent) 在 UI 线程中处理消息;非 UI 或收到退出消息后仍保持 wait-any 语义。

cancelEvent 可以是:

省略或传入 null 保持旧行为;描述符本身不是事件对象,须先 open。

结果 wait 首返回值 waitOne 首返回值 第二返回值
取得 mutex true 1 null
取得已弃置 mutex true 1 "abandoned"
取消 false null "cancelled"
超时 false null "timeout"
失败 false null "failed"

超时/原生失败的第三返回值是等待返回码(例如 258、0xFFFFFFFF),不是 GetLastError();取消没有伪造的原生返回码。正常与弃置取得都会登记次数,取消/超时/失败不登记。

取消事件位于等待数组的第一项,两个条件同时就绪时取消优先。这是等待时的选择,不是取消与所有权之间的事务:如果已经取得 mutex,随后才到达取消请求,本次成功仍有效,业务方负责检查与释放。

每个对象只兜底自己显式取得的次数。提取裸句柄后绕过对象取得所有权,由提取者负责配对释放;本库不追踪任意跨包装对象操作。

跨线程:只传描述符

import thread.cancellation;

var source = thread.cancellation();
var ready = thread.event(,true,false);
var worker = thread.create(function(token,ready){
    import thread.cancellation;
    var observer,err = thread.cancellation.open(token);
    if(!observer) return 2;
    ready.set();
    var cancelled = observer.wait(3000);
    observer.close();
    if(cancelled) return 1;
    return 0;
},source.token,ready);

ready.wait(2000);
source.cancel();
thread.wait(worker,4000);
print(thread.getExitCode(worker)); // 1:已观察到取消
raw.closeHandle(worker);
ready.close();
source.close(); // 保持 source 存活直到 worker 结束

描述符是 {schema=1;eventName="..."},可经 JSON 编解码后交给其他进程。不要修改内容,不直接传递 source/observer 包装对象。观察者在自己的线程调用 thread.cancellation.open(token);需要发出请求的一方可调用 thread.cancellation.cancel(token)。

同一登录会话、具备相应权限的进程可共享;默认使用 Local\ 命名空间。跨身份/会话的权限配置不是本库职责。

API 与生命周期

取消源持有事件引用,观察者各持独立、不可继承的 SYNCHRONIZE 句柄,不具备 SetEvent/ResetEvent 权限。已取消的事件始终保持有信号;当前及后来打开的多个观察者都能收到取消。

close 不等于 cancel。源关闭后,已打开的观察者仍然有效;所有引用关闭后事件消失,旧描述符将打开失败。因此控制方应保留源直到全部 worker 结束,避免尚未 open 的 worker 失去事件。

observer.handle 仅供借用,不能自行关闭或改写。描述符可用于请求取消,应只交给可信参与方;这不是防恶意进程的安全沙箱,不保证其他直接访问 Win32 API 的代码不能重置或重建同名对象。

Markdown 格式