随笔一则
Meme: Rust 生命周期与内部可变性
use ;
;
非常平平无奇的代码. 于是有新的需求: 想缓存 get 的结果 (把按 domain:example.com
匹配到的 sub.example.com
当 full:sub.example.com
写入表内), 达到下次读哈希表一次就能把 Peer 读出来.
有这么几个方案:
- 改用三方库
dashmap
提供的 DashMap, 类似 RwLock 但 API 层面 是 Lock-free 的. - 套一层 Mutex / RwLock.
RefCell毙掉, 我们需要 Send + Sync, 应该用其线程安全版本: RwLock
但事实上都是不可行的, 为什么? 欢迎 Rust 初学者自行查阅资料 (问 AI 也行)~
答案 (实际上编译器已经提示了):
对于具有内部可变性的 Cell 类似物, 子类型型变要求是不变 (invariant) 的1. 本例中 DashMap 内部用了 lock_api 库的 RwLock, 这玩意内部用了 UnsafeCell, 故相应字段涉及的泛型类型 K 要求是不变的.
不能返回本地变量 (拿到的 &Peer 只能活得和上锁后拿到的 Guard 一样久). 起码在当前的 API 设计下不能这么干. 当然, 写出来
get_and_map
一类的奇怪 API 也不是不行.
评价: 写 Rust 的福报