mc::io::io_buffer

概述

mc::io::io_buffer 是支持引用计数共享、头尾预留和链式组织的拥有型字节缓冲区,适用于网络协议和流式 I/O。

主要特性

  • 复制构造只共享底层存储,clone() 才创建独立字节副本。
  • 多个 buffer 可以组成链,链迭代不会调用 normalize(),也不会复制 payload。
  • slice() 按整条链的逻辑偏移生成共享切片,跨节点时保留链结构。
  • 支持接管外部内存、自定义释放函数以及 headroom/tailroom。
  • 写共享数据前可通过 unshare() 建立独占副本。
  • copy_buffer(string_view) 自动推导长度;as_string_view() / to_string() 便捷转字符串(无需手动 reinterpret_cast)。

基本用法

创建并写入缓冲区

#include <mc/io/io_buffer.h>

int main()
{
    auto buffer = mc::io::io_buffer::create(128);
    const char text[] = "hello";
    buffer->write(text, sizeof(text) - 1);
    return buffer->length() == 5 ? 0 : 1;
}

逐段消费链而不合并

#include <mc/io/io_buffer.h>
#include <string>

int main()
{
    auto head = mc::io::io_buffer::copy_buffer("ab", 2);
    head->append_to_chain(mc::io::io_buffer::copy_buffer("cd", 2));

    std::string output;
    for (const auto segment : *head) {
        output.append(segment.data(), segment.size());
    }
    return output == "abcd" ? 0 : 1;
}

创建零 payload 拷贝的链切片

#include <mc/io/io_buffer.h>

int main()
{
    auto head = mc::io::io_buffer::copy_buffer("abc", 3);
    head->append_to_chain(mc::io::io_buffer::copy_buffer("def", 3));

    auto slice = head->slice(2, 3); // "cde",只复制节点元数据
    return slice.compute_chain_length() == 3 && slice.is_shared() ? 0 : 1;
}

API 详细说明

io_buffer

方法 参数 返回值 异常 线程安全 说明
io_buffer() 无 新对象 不抛出 否 创建空 buffer。
复制构造/赋值 const io_buffer& 共享副本 内存分配失败 否 复制链节点元数据,共享每段底层存储。
移动构造/赋值 io_buffer&& 所有权转移后的对象 不抛出 否 转移整条链。
create capacity unique_ptr<io_buffer> bad_alloc_exception 是 分配指定最小容量。
take_ownership buf,capacity,length,free_fn,user_data unique_ptr<io_buffer> invalid_arg_exception 是 接管外部内存。
wrap buf,length unique_ptr<io_buffer> invalid_arg_exception 是 非拥有地包装外部内存;调用方保证生命周期。
copy_buffer data,length,headroom,tailroom unique_ptr<io_buffer> invalid_arg_exception、bad_alloc_exception 是 复制输入字节。
data/mutable_data 无 数据指针 不抛出 只读访问可并发;写访问否 返回当前节点有效数据。
length/capacity/headroom/tailroom 无 size_t 不抛出 只读访问可并发 查询当前节点,不统计后续链节点。
buffer/tail/buffer_end/mutable_tail 无 指针 不抛出 只读访问可并发;写访问否 查询当前节点内存边界。
empty/is_shared/is_chained 无 bool 不抛出 只读访问可并发 查询当前节点或链状态。
begin/end 无 const_iterator 不抛出 只读访问可并发 逐节点返回非空 string_view,不合并链。
append/prepend amount 无 不抛出 否 在已有 tailroom/headroom 内扩展有效区;空间不足时不修改。
trim_start/trim_end amount 无 不抛出 否 缩短当前节点有效区。
clear 无 无 不抛出 否 清空当前节点数据。
reserve min_headroom,min_tailroom 无 bad_alloc_exception、runtime_exception 否 必要时移动或扩容当前节点。
align alignment 填充字节数 bad_alloc_exception、runtime_exception 否 用零填充尾部以满足长度对齐。
write data,length 写入字节数 bad_alloc_exception、runtime_exception 否 追加字节,必要时扩容。
write_at_offset offset,data,length 写入字节数 bad_alloc_exception、runtime_exception 否 在逻辑偏移写当前节点。
write_value/write_value_at_offset 值、偏移、字节序 写入字节数 同 write 否 按指定字节序写 trivially-copyable 值。
read 偏移、长度或目标指针 view 或字节数 越界异常、runtime_exception 只读访问可并发 精确读取当前节点。
try_read 偏移、长度或目标指针 bool 或 view 不抛出 只读访问可并发 越界时返回失败/空 view。
read_some 偏移、最大长度或目标指针 view 或字节数 参数异常、runtime_exception 只读访问可并发 读取当前节点内可用部分。
read_value 偏移、字节序 值或 bool 值返回重载可能越界 只读访问可并发 按指定字节序读取值。
ensure_tailroom amount bool 不传播分配异常 否 尝试保证尾部空间。
clone 无 独立 buffer 链 bad_alloc_exception、runtime_exception 只读访问可并发 深拷贝所有链节点。
unshare 无 无 bad_alloc_exception、runtime_exception 否 对共享节点执行 copy-on-write。
compute_chain_length 无 size_t 不抛出 只读访问可并发 统计整条链有效字节数。
slice offset,length io_buffer invalid_arg_exception、内存分配异常 只读访问可并发 创建共享链切片,不复制 payload。
append_to_chain unique_ptr<io_buffer>&& 无 不抛出 否 把输入的整条链拼到末尾。
insert_after unique_ptr<io_buffer>&& 无 不抛出 否 把输入的整条链插到当前节点之后。
normalize 无 连续 string_view bad_alloc_exception、runtime_exception 否 多节点时复制并替换为单一连续 buffer。
as_string_view 无 string_view 不抛出 只读访问可并发 当前节点的有效数据视图(单节点零拷贝,链式时只返回当前节点)。
to_string 无 mc::string bad_alloc_exception、runtime_exception 只读访问可并发 转为连续字符串(链式安全,内部 copy + normalize,不改原 buffer)。
copy_buffer (重载) string_view unique_ptr<io_buffer> 同上 是 从 string_view 复制(自动推导长度)。

const_iterator

方法 参数 返回值 异常 线程安全 说明
operator* 无 当前节点 string_view 不抛出 只读访问可并发 view 生命周期不超过 buffer 链及其共享存储。
operator++ 无 迭代器 不抛出 只读访问可并发 前进到下一链节点。
operator==/!= 两个迭代器 bool 不抛出 是 比较迭代位置。

最佳实践

✅ 流式 I/O 使用范围 for 逐段消费,避免仅为写文件或发 socket 调用 normalize()。

✅ 需要保留局部字节时使用 slice();切片与原 buffer 共享存储,应当按只读数据传递。

❌ 不要修改 wrap() 引用的已失效外部内存,也不要让外部内存早于 buffer 销毁。

❌ 不要把 length() 当作整条链长度;链式数据应使用 compute_chain_length()。