为 log 实现的无锁 Ringbuffer」的摘要信息

这两天在改 log 模块。我们需要一个并发写 log 的模块,它有多个 log 生产者一个消费者,这个唯一的消费者在 log 线程中把 log 数据持久化。 大多数 log 生产者是在第三方库的 callback 函数中调用的,比如 bgfx ,如果写 log 不够快的话,就会阻塞渲染。这个 callback 需要自己保证线程安全,因为 bgfx 支持多线程渲染,所以写 log 的 callback 可能在不同的线程触发。 过去在实现 bgfx 的 luabinding 时,我实现了一个简单的 mpsc 队列,get_log 这个函数就是那个单一消费者,它取出队列中所有的 log 信息,返回到 lua 虚拟机中。 它是用 spin_lock 实现的。这两天,我想应该可以实现一个更通用的无锁版本。 在我的需求中,log 信息是允许丢掉的。所以我开了一个固定大小的 ringbuffer 收集各个不同线程生产出来的 log ,然后在一个单一线程定期(通常是一个渲染帧一次)取出它们。只要取的频率够高,而生产的 log 数量不那么快的话,一个合适大小的 ringbuffer 就能以最简单的数据结构解决问题。 我觉得一个无锁结构的 log 系统需要两个 ringbuffer 。 我们缓存的 log 条目数目上限估计不用太大,4096 或许是个合适的数字:即,每帧不会产生超过 4000 条 log 。那么就用一个 4096 的固定数组即可。 实现这么一个 ringbuffer 需要有两个 64bit 的原子变量,head 和 tail 。让多个生产者依次尾进头出这个队列 ring buffer。写入数据保持这样的流程: index = fetch and add tail, 1 buffer[index % 4096] = meta 这里只需要记录 meta 信息,而不是 log 的文本...