scope-local
路径:
components/scope-local类型:库 crate 分层:组件层 / 可切换局部存储层 版本:0.1.2文档依据:当前仓库源码、Cargo.toml、src/lib.rs、src/item.rs、src/scope.rs、src/boxed.rs以及 StarryOS 集成代码
scope-local 提供的是一种“可切换 scope 的局部存储”,而不是语言级 TLS。它把若干 scope_local! 声明的静态项注册进同一个 registry,再为每个 Scope 分配一组对应的数据槽位;运行时通过当前 CPU 的一个 per-CPU 指针决定“当前激活的是哪一个 scope”。这样一来,代码访问 LocalItem<T> 时,看到的不是全局唯一对象,而是“当前 scope 中的那一份值”。
架构设计
设计定位
scope-local 解决的问题与 TLS 类似但 不相同:
- 需要一组“当前上下文局部”的数据
- 但这个“当前上下文”不一定是线程,也可能是进程、任务域或某个显式切换的执行环境
因此它采用的不是编译器 TLS,而是:
- 链接期收集静态注册项
- 运行时分配
Scope - 通过 per-CPU 指针显式切换当前 scope
模块结构
| 模块 | 作用 |
|---|---|
item.rs | 注册项、registry、LocalItem 与 scope_local! 宏 |
scope.rs | Scope、ActiveScope、全局默认 scope |
boxed.rs | 单个 registry 项的堆上存储盒 ItemBox |
1.3 核心数据模型
Item
每个 scope_local! 静态项在链接后都会变成一个注册项,放进 scope_local 段中。Registry 会通过链接符号遍历这些项,并为每个项分配一个稳定下标。
Scope
Scope 本质上是一组 ItemBox 的集合,每个下标对应一个注册项。也就是说,一个 Scope 表示“当前这组局部变量的完整实例化集合”。
ItemBox
负责单个注册项的实际堆分配、初始化和 drop。它把类型 T 的构造/析构逻辑与 Scope 的整体布局解耦开来。
ActiveScope
负责决定“当前 CPU 正在使用哪个 Scope”。其内部状态并不保存在 TLS,而是保存在一个 per-CPU 静态槽位里。
1.4 当前 scope 的获取机制
当前 scope 选择逻辑的关键是:
ACTIVE_SCOPE_PTR是 per-CPU 变量- 若它为 0,则回退到惰性初始化的
GLOBAL_SCOPE - 若不为 0,则把它解释为当前
Scope的数据起始位置
这说明 scope-local 不是“每线程永远固定一个局部对象”,而是“当前 CPU 可以切换正在使用的 scope”。