Rust in Everything
基于 crossbeam-queue 0.3.14

queue 与 skiplist

这一部分是两个小 crate,各一章:

  1. ArrayQueue 与 SegQueue:crossbeam-queue 0.3.14,两个文件共 1358 行。ArrayQueue 和 array channel 是同一个 stamp 环,SegQueue 和 list channel 是同一条块链表,都去掉了阻塞和断开。读过 06 部分的话,这一章主要看多出来的东西:force_push、len() 的循环、push_mut / pop_mut。
  2. 并发跳表:crossbeam-skiplist 0.1.3,以 main 上的 tag crossbeam-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 用分片 SkipMapTinyUFO
sqlx 连接池idle_conns 是 ArrayQueue,长度另用原子计数获取连接

frontmatter 里的 source 写的是 crossbeam-queue 0.3.14;跳表一章单独标 crossbeam-skiplist 0.1.3。

💬 关联讨论

发起讨论
加载中...