用户层 API
前面几部分从运行时内部往外看:任务怎么分配、调度器怎么取任务、驱动怎么唤醒。这一部分反过来,从用户代码里最常见的几个 API 出发,往下找到它们落在哪里。
- spawn 全路径:
tokio::spawn到任务进队列的每一跳。大 future 先装箱;在 worker 线程上 spawn 进 LIFO 槽,在别的线程上 spawn 进注入队列。 - select! 与 join!:两个宏展开后都是一个
poll_fn。select!每次 poll 随机选起点,一个分支完成就 drop 其余分支,cancel safety 问题由此而来。 - JoinSet、LocalSet、task_local:
JoinSet用两条链表记录哪些任务完成了;LocalSet是一个自带队列的小调度器,跑在宿主任务里面;task_local!在每次 poll 前后把值换进换出线程本地变量。
flowchart TB
spawn["tokio::spawn"] --> bind["OwnedTasks::bind"]
bind --> sched{在本运行时的 worker 上?}
sched -->|是| lifo[LIFO 槽 / 本地队列]
sched -->|否| inject[注入队列]
sel["select! / join!"] --> pf[一个 poll_fn]
pf --> branches[在当前任务里轮流 poll 各分支]
js[JoinSet] --> spawn
ls[LocalSet] --> own[自己的本地队列]
这一部分用到的内部结构都在前面讲过:任务的分配和 OwnedTasks 见「03 任务」,LIFO 槽、注入队列和预算见「04 调度器」。
💬 关联讨论
发起讨论加载中...