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()。