#[repr(C)]pub(super) struct GlobalLogBuffer {
writer_data: CachePadded64<WriterData>,
reader_data: CachePadded64<ReaderData>,
buffer: [LogEntry; 53],
unread_bytes: AtomicUsize,
}Expand description
存储日志条目的锁无关环形缓冲区
采用多生产者单消费者 (MPSC) 设计,其中:
- 多个 CPU 可以并发地写入日志而无需阻塞
- 单个消费者线程按顺序读取日志
Fields§
§writer_data: CachePadded64<WriterData>写入侧数据(由生产者更新)
reader_data: CachePadded64<ReaderData>读取侧数据(由消费者更新)
buffer: [LogEntry; 53]固定大小的日志条目数组
unread_bytes: AtomicUsize记录未读日志的总字节数
Implementations§
Source§impl GlobalLogBuffer
impl GlobalLogBuffer
Sourcepub(super) fn write(&self, entry: &LogEntry)
pub(super) fn write(&self, entry: &LogEntry)
将日志条目写入缓冲区
这是一个锁无关操作,执行以下步骤:
- 原子地获取一个唯一的序列号(票据)
- 使用模运算计算目标槽位索引
- 检查并处理潜在的缓冲区满(覆盖)逻辑
- 将日志数据复制到槽位(不包括 seq 字段)
- 使用 Release 内存屏障原子地设置 seq 来发布条目
- 增加未读字节计数
Sourcefn handle_overwrite(&self, current_seq: usize)
fn handle_overwrite(&self, current_seq: usize)
处理缓冲区溢出,必要时推进读取指针
当缓冲区满且新的写入将覆盖未读条目时,此函数:
- 检测溢出条件
- 计算将被覆盖的条目数
- 更新丢弃计数
- 使用 CAS 循环原子地推进读取指针
Sourcepub(super) fn read(&self) -> Option<LogEntry>
pub(super) fn read(&self) -> Option<LogEntry>
从缓冲区读取下一个日志条目
如果没有可用条目,则返回 None。这是一个锁无关的
单消费者操作,使用 Acquire 内存顺序确保与生产者的正确同步。
读取后会减少未读字节计数。
Sourcepub(super) fn unread_bytes(&self) -> usize
pub(super) fn unread_bytes(&self) -> usize
返回未读日志的总字节数(格式化后)
Sourcepub(super) fn dropped_count(&self) -> usize
pub(super) fn dropped_count(&self) -> usize
返回由于缓冲区溢出而丢弃的日志总数
Sourcepub(super) fn reader_index(&self) -> usize
pub(super) fn reader_index(&self) -> usize
获取当前可读取的起始索引(读指针位置)
Sourcepub(super) fn writer_index(&self) -> usize
pub(super) fn writer_index(&self) -> usize
获取当前写入位置(下一个要写入的索引)