queue 与 skiplist
这一部分是两个小 crate,各一章:
- ArrayQueue 与 SegQueue:crossbeam-queue 0.3.14,两个文件共 1358 行。
ArrayQueue和 array channel 是同一个 stamp 环,SegQueue和 list channel 是同一条块链表,都去掉了阻塞和断开。读过 06 部分的话,这一章主要看多出来的东西:force_push、len()的循环、push_mut/pop_mut。 - 并发跳表:crossbeam-skiplist 0.1.3,以
main上的 tagcrossbeam-skiplist-0.1.3为准(它不在本卷其他 crate 的发布提交上,原因见那一章开头)。一个节点一次分配,删除先标记整座塔,节点的释放先过引用计数、再交给 crossbeam-epoch。
flowchart LR utils["crossbeam-utils:Backoff、CachePadded"] --> queue["crossbeam-queue"] utils --> chan["crossbeam-channel"] utils --> epoch["crossbeam-epoch"] epoch --> skip["crossbeam-skiplist"] chan -. "同一个 stamp 环" .-> aq["ArrayQueue"] chan -. "同一条块链表" .-> sq["SegQueue"] queue --> aq queue --> sq skip --> map["SkipMap / SkipSet"]
queue 不依赖 epoch:ArrayQueue 的槽是预分配的,SegQueue 的块由读者按 READ / DESTROY 位接力释放,和 list channel 一样。skiplist 必须依赖 epoch:节点从跳表里摘下以后,别的线程可能还拿着它的指针在遍历,只能延迟释放。
本卷读到的使用者:
| 项目 | 用法 | 页面 |
|---|---|---|
pingora pingora-pool | 每组连接一个 16 格 ArrayQueue 热队列 | 连接池 |
| pingora TinyUFO | 两条 SegQueue<Key>;new_compact 用分片 SkipMap | TinyUFO |
| sqlx 连接池 | idle_conns 是 ArrayQueue,长度另用原子计数 | 获取连接 |
frontmatter 里的 source 写的是 crossbeam-queue 0.3.14;跳表一章单独标 crossbeam-skiplist 0.1.3。
💬 关联讨论
发起讨论加载中...