docs: explain Tessera modules and execution flows in Chinese
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
//! owner/key 管理的异步任务与协作式源函数调度。弱索引用于查找,回调、等待对象和协程帧是托管图中的真实边。
|
||||
//! 任务可能处于等待 I/O、定时器、可执行协程或等待另一任务的状态;取消 owner/key 不能让晚到结果再次执行。
|
||||
//! 调度使用有界量子和公平推进;await 挂起后保留操作数与帧,不重放此前副作用。失败和依赖环有明确处理路径。
|
||||
//!
|
||||
//! Owner-managed asynchronous work. Only weak identities enter the scheduler;
|
||||
//! callbacks and scopes are ordinary traced edges in the Aster object graph.
|
||||
use std::{
|
||||
@@ -24,6 +28,7 @@ const MAX_READY: usize = 64;
|
||||
type Index = Arc<Mutex<Vec<WeakObjectRef>>>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
/// 任务对源代码可见的生命周期状态,完成/取消/失败各有不同 await 语义。
|
||||
enum State {
|
||||
Pending,
|
||||
Running,
|
||||
@@ -32,6 +37,7 @@ enum State {
|
||||
Failed,
|
||||
}
|
||||
impl State {
|
||||
/// 返回内部枚举或对象对应的稳定源名称。
|
||||
fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Pending => "pending",
|
||||
@@ -44,6 +50,7 @@ impl State {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// 托管异步对象,保存 owner/key、结果与真正拥有的回调/协程/等待引用。
|
||||
struct Task {
|
||||
owner: WeakObjectRef,
|
||||
key: String,
|
||||
@@ -60,15 +67,19 @@ struct Task {
|
||||
result: Option<Value>,
|
||||
}
|
||||
impl ObjectPayload for Task {
|
||||
/// 提供受检查的 Any 下转型入口,让宿主按具体 payload 类型读取数据。
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
/// 返回运行时诊断/类型检查使用的稳定 payload 名称。
|
||||
fn kind_name(&self) -> &'static str {
|
||||
"tessera-task"
|
||||
}
|
||||
/// 声明此 payload 的赋值遵循引用身份语义,避免把内部宿主状态当作可复制值。
|
||||
fn reference_assignment_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
/// 把 Task 状态投影成 await 的就绪、等待、取消或失败结果,不在等待期间主动轮询执行。
|
||||
fn poll_await(&self) -> Result<endor_core::AwaitPoll, VmError> {
|
||||
match self.state {
|
||||
State::Pending | State::Running => Ok(endor_core::AwaitPoll::Pending),
|
||||
@@ -86,6 +97,7 @@ impl ObjectPayload for Task {
|
||||
)),
|
||||
}
|
||||
}
|
||||
/// 枚举本对象真正拥有的托管强引用,供 Aster 引用追踪和循环回收使用。
|
||||
fn trace(&self, visit: &mut dyn FnMut(ObjectRef)) {
|
||||
if let Some(callback) = self.callback {
|
||||
visit(callback);
|
||||
@@ -101,15 +113,18 @@ impl ObjectPayload for Task {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// 统一构造本模块的参数错误,让调用方停止处理无效输入。
|
||||
fn invalid(message: &'static str) -> VmError {
|
||||
VmError::InvalidArgument(message)
|
||||
}
|
||||
/// 从源值中提取并检查托管对象身份,错误类型沿 VM 错误返回。
|
||||
fn object(value: &Value) -> Result<ObjectRef, VmError> {
|
||||
match value {
|
||||
Value::Object(object) => Ok(*object),
|
||||
_ => Err(invalid("task owner and callback must be managed objects")),
|
||||
}
|
||||
}
|
||||
/// 取得 owner 关联的托管任务作用域,供 key 替换和取消使用。
|
||||
fn scope(store: &ObjectStore, owner: ObjectRef) -> Result<Option<ObjectRef>, VmError> {
|
||||
let payload = store.object(owner)?.payload();
|
||||
if let Some(value) = payload.as_any().downcast_ref::<Block>() {
|
||||
@@ -132,6 +147,7 @@ fn scope(store: &ObjectStore, owner: ObjectRef) -> Result<Option<ObjectRef>, VmE
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
/// 为可拥有任务的对象安装作用域,真实引用仍由托管图追踪。
|
||||
fn install_scope(
|
||||
cx: &mut NativeContext<'_>,
|
||||
owner: ObjectRef,
|
||||
@@ -155,6 +171,7 @@ fn install_scope(
|
||||
}
|
||||
cx.set_attr(owner, SCOPE, Value::Object(scope))
|
||||
}
|
||||
/// 检查任务的 owner 仍有效且任务具备交付条件,避免晚到结果复活已关闭页面。
|
||||
fn eligible(store: &ObjectStore, owner: ObjectRef, desktop: ObjectRef) -> Result<bool, VmError> {
|
||||
let payload = store.object(owner)?.payload();
|
||||
if let Some(mount) = payload.as_any().downcast_ref::<Mount>() {
|
||||
@@ -194,6 +211,7 @@ fn eligible(store: &ObjectStore, owner: ObjectRef, desktop: ObjectRef) -> Result
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
/// 检查弱索引对应的任务是否仍是 owner/key 当前登记的那一项。
|
||||
fn current(
|
||||
store: &ObjectStore,
|
||||
owner: ObjectRef,
|
||||
@@ -210,6 +228,7 @@ fn current(
|
||||
|
||||
/// Called at the actual close/detach boundary, including close-then-reopen in
|
||||
/// one language input. A later appearance never revives these identities.
|
||||
/// 取消某个 owner 的全部任务,防止页面/窗口生命周期结束后继续执行回调。
|
||||
pub fn cancel_owner(cx: &mut NativeContext<'_>, owner: ObjectRef) -> Result<(), VmError> {
|
||||
let Some(scope) = scope(cx.store(), owner)? else {
|
||||
return Ok(());
|
||||
@@ -233,6 +252,7 @@ pub fn cancel_owner(cx: &mut NativeContext<'_>, owner: ObjectRef) -> Result<(),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
/// 当前宿主 API 的操作分类,分派代码负责参数校验与状态更新。
|
||||
enum Operation {
|
||||
Timer,
|
||||
Sleep,
|
||||
@@ -241,6 +261,7 @@ enum Operation {
|
||||
Spawn,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
/// 创建定时/I/O/协作任务时的原生调用适配器。
|
||||
struct After {
|
||||
operation: Operation,
|
||||
provider: crate::io_tasks::Provider,
|
||||
@@ -251,13 +272,16 @@ struct After {
|
||||
desktop: ObjectRef,
|
||||
}
|
||||
impl NativeCallable for After {
|
||||
/// 给出参数与返回值的托管类型契约;实际操作在 invoke 中执行。
|
||||
fn signature(&self) -> Option<endor_core::CallSignature> {
|
||||
Some(self.signature.clone())
|
||||
}
|
||||
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
|
||||
fn arity(&self) -> Option<endor_core::CallArity> {
|
||||
Some(self.signature.arity)
|
||||
}
|
||||
|
||||
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
|
||||
fn invoke(&self, cx: &mut NativeContext<'_>, args: &[Value]) -> Result<NativeResult, VmError> {
|
||||
if self.quiescing.load(Ordering::Acquire) {
|
||||
return Err(invalid("runtime is exiting; new tasks are forbidden"));
|
||||
@@ -459,6 +483,7 @@ impl NativeCallable for After {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// 该原生能力的查询/操作分类,方法包装用它选择具体实现。
|
||||
enum Query {
|
||||
Cancel,
|
||||
Status,
|
||||
@@ -467,19 +492,23 @@ enum Query {
|
||||
Error,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
/// 保存 owner、签名或操作枚举的原生方法适配器,统一由 VM 调用。
|
||||
struct Method {
|
||||
signature: endor_core::CallSignature,
|
||||
query: Query,
|
||||
desktop: ObjectRef,
|
||||
}
|
||||
impl NativeCallable for Method {
|
||||
/// 给出参数与返回值的托管类型契约;实际操作在 invoke 中执行。
|
||||
fn signature(&self) -> Option<endor_core::CallSignature> {
|
||||
Some(self.signature.clone())
|
||||
}
|
||||
/// 声明宿主可调用对象接受的参数个数,供 VM 在执行前检查。
|
||||
fn arity(&self) -> Option<endor_core::CallArity> {
|
||||
Some(endor_core::CallArity::exact(1))
|
||||
}
|
||||
|
||||
/// VM 调入本宿主能力的入口;按所属操作解码参数并返回托管值或后续调用。
|
||||
fn invoke(&self, cx: &mut NativeContext<'_>, args: &[Value]) -> Result<NativeResult, VmError> {
|
||||
let [value] = args else {
|
||||
return Err(invalid("Task methods accept no arguments"));
|
||||
@@ -561,6 +590,7 @@ impl NativeCallable for Method {
|
||||
}
|
||||
}
|
||||
|
||||
/// 弱任务索引、公平调度位置和 provider,索引不会单独把任务保活。
|
||||
pub struct Scheduler {
|
||||
index: Index,
|
||||
runnable: Arc<AtomicBool>,
|
||||
@@ -569,15 +599,18 @@ pub struct Scheduler {
|
||||
provider: crate::io_tasks::Provider,
|
||||
}
|
||||
impl Scheduler {
|
||||
/// 停止接收该域的新任务工作,为关闭/替换运行时做准备。
|
||||
pub fn quiesce(&self, vm: &mut Vm) -> Result<usize> {
|
||||
self.quiescing.store(true, Ordering::Release);
|
||||
self.cancel_all(vm)
|
||||
}
|
||||
/// 检查是否有可推进的协程,而不是仅仅存在正在等待外部结果的任务。
|
||||
pub fn has_cooperative_work(&self) -> bool {
|
||||
self.runnable.load(Ordering::Acquire)
|
||||
}
|
||||
/// Mutation boundaries collect unreachable owner/callback cycles before
|
||||
/// this weak lookup. Idle timer polling does not rescan the entire heap.
|
||||
/// 在当前 VM 中有界交付就绪任务、执行回调或推进协程;开始布局后由外层刷新流程继续。
|
||||
pub fn poll(&self, vm: &mut Vm, limit: usize) -> Result<usize> {
|
||||
anyhow::ensure!((1..=MAX_READY).contains(&limit), "invalid task poll limit");
|
||||
// Provider threads only fill the mailbox. Only this VM worker updates
|
||||
@@ -731,6 +764,7 @@ impl Scheduler {
|
||||
self.prune(vm)?;
|
||||
Ok(work)
|
||||
}
|
||||
/// 取消当前域全部任务,切断回调、协程和等待交付资格。
|
||||
pub fn cancel_all(&self, vm: &mut Vm) -> Result<usize> {
|
||||
let snapshot = self
|
||||
.index
|
||||
@@ -753,6 +787,7 @@ impl Scheduler {
|
||||
self.runnable.store(false, Ordering::Release);
|
||||
Ok(count)
|
||||
}
|
||||
/// 移除已释放的弱任务索引,索引本身不让任务或其 owner 存活。
|
||||
fn prune(&self, vm: &mut Vm) -> Result<()> {
|
||||
let mut index = self
|
||||
.index
|
||||
@@ -789,6 +824,7 @@ impl Scheduler {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/// 沿等待链检查任务依赖环,防止 await 永远无法被满足。
|
||||
fn cyclic_wait(vm: &Vm, source: ObjectRef, mut target: ObjectRef) -> Result<bool> {
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
loop {
|
||||
@@ -805,6 +841,7 @@ fn cyclic_wait(vm: &Vm, source: ObjectRef, mut target: ObjectRef) -> Result<bool
|
||||
}
|
||||
}
|
||||
|
||||
/// 恢复已保存的源函数帧,处理完成、软量子挂起或 await 等待,保留已发生的副作用。
|
||||
fn advance_coroutine(vm: &mut Vm, reference: ObjectRef) -> Result<()> {
|
||||
let mut task = vm.payload::<Task>(reference, "Task")?.clone();
|
||||
let coroutine = if let Some(coroutine) = task.coroutine {
|
||||
@@ -897,6 +934,7 @@ fn advance_coroutine(vm: &mut Vm, reference: ObjectRef) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 记录回调执行失败并沿运行时故障规则停止后续不安全的交付。
|
||||
fn fail_callback(vm: &mut Vm, reference: ObjectRef, message: &str) -> Result<()> {
|
||||
let mut task = vm.payload::<Task>(reference, "Task")?.clone();
|
||||
task.error = Some(message.chars().take(1024).collect::<String>().into());
|
||||
@@ -904,6 +942,7 @@ fn fail_callback(vm: &mut Vm, reference: ObjectRef, message: &str) -> Result<()>
|
||||
finish(vm, reference, State::Failed)
|
||||
}
|
||||
|
||||
/// 将任务转入终态并释放回调、provider 租约、协程和等待引用;取消还会清除保存的结果。
|
||||
fn finish(vm: &mut Vm, reference: ObjectRef, state: State) -> Result<()> {
|
||||
let mut task = vm.payload::<Task>(reference, "Task")?.clone();
|
||||
if !matches!(task.state, State::Pending | State::Running) {
|
||||
@@ -934,6 +973,7 @@ fn finish(vm: &mut Vm, reference: ObjectRef, state: State) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 把本模块的类型、方法或能力注册到所属运行时上下文。
|
||||
pub fn install(
|
||||
vm: &mut Vm,
|
||||
roots: &mut Vec<ObjectRef>,
|
||||
|
||||
Reference in New Issue
Block a user