跳到主要内容

Pipe 单向管道

Pipe 将一个 WritePort 与一个 ReadPort 通过同一条无锁字节队列连接成单向数据通道:写端写入的字节可被读端直接读取,无需端口间的中间拷贝(仅有一次写入到共享队列的拷贝)。该类适用于在线程/任务/ISR 与任务之间进行高效的数据转发与环回测试。


特性概览

  • 零额外拷贝:写端写入 → 直接进入共享队列 → 读端从同一队列取出。
  • ISR 友好:读端推进通过 ProcessPendingReads(in_isr),可在 ISR 或任务上下文中触发。
  • 语义与 ReadPort/WritePort 一致:阻塞/回调/轮询等完成方式统一由 Operation 控制。

公共接口

class Pipe {
public:
// 使用给定共享数据队列容量(字节)构造
Pipe(size_t buffer_size);

// 非拷贝/非赋值
Pipe(const Pipe&) = delete;
Pipe& operator=(const Pipe&) = delete;
~Pipe();

// 端口访问
ReadPort& GetReadPort();
WritePort& GetWritePort();
};
  • buffer_size:共享队列总容量(字节),用于承载写入的数据。创建后不可更改。
  • 当前实现内部实际构造成 ReadPort(0)WritePort(1, buffer_size)
    • 读端自身不持有独立数据队列容量;
    • 写端元信息队列固定为 1 槽,数据字节队列容量为 buffer_size
  • Pipe 不直接暴露 Size()/Reset() 等方法——请通过 GetReadPort() / GetWritePort() 使用对应端口接口。

使用方式

Pipe 当作“自带回环驱动”的内存管道使用:写端写入会触发 WriteFun,进而推进读端处理挂起读取。

LibXR::Pipe pipe(256);

auto& r = pipe.GetReadPort();
auto& w = pipe.GetWritePort();

// 典型:先发起读(可能进入 PENDING),再写入推进
uint8_t buf[16];
LibXR::ReadOperation rop(status_or_cb_or_sem);
LibXR::WriteOperation wop(status_or_cb_or_sem);

r({buf, sizeof(buf)}, rop); // 可能挂起
w({some_data, some_len}, wop); // 写入后会推进 r.ProcessPendingReads(...)

备注:Pipe 的读侧是“被动推进”的:需要写侧触发(或外部主动调用 ProcessPendingReads)才能完成挂起读请求;这一点与 ReadPort 的模型保持一致。

另一个当前实现边界是:WriteFun 会从写端的 queue_info_ 中弹出一个 WriteInfoBlock,若弹出失败当前实现会断言并返回 ErrorCode::EMPTY。这说明 Pipe 依赖的并不是“任意写端回调协议”,而是当前 WritePort 的既有入队/完成语义。