Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

块式读写器(block_read_writer)

block_read_writer<T> 为“块式 I/O”提供一个轻量的用户态缓冲与读写指针管理器。 它在调用方与底层原始 I/O 对象(如 file)之间维护一段活动缓冲区与独立的读/写位置, 使顺序与随机读写更易用,同时保留“无用户态缓冲的原始 I/O”的可控性: 未 flush() 前的数据仅对当前对象可见,flush() 后才落到下层 I/O。

要点

  • 读写统一接口:顺序/随机读写、独立 seekg/seekptellg/tellp
  • 显式持久化:flush() 前写入仅缓存在内存,flush() 后写入到底层 I/O
  • 读可见性:未 flush() 的写入,对同一 block_read_writer 的后续读取是可见的
  • 析构自动刷写:对象析构时会调用 flush(),尝试将缓冲写入到底层 I/O
  • 协程语义:read() 可被打断;write()flush() 不可打断
  • 模板约束:T 需满足 block_read_write 概念(例如 asco::io::file

快速上手

using asco::io::file;
using asco::io::buffer;
using asco::io::seekpos;
using asco::block_read_writer;

auto r = co_await file::at("/tmp/demo.bin")
        .read()
        .write()
        .create()
        .truncate()
        .mode(0644)
        .open();
if (!r) co_return;
block_read_writer<file> brw(std::move(*r));

// 写入两段数据(此时仅缓存在 brw 中)
co_await brw.write(buffer("Hello"));
co_await brw.write(buffer("World"));
assert(brw.tellp() == 10);

// 读取(未 flush 的写入对同一 brw 可见)
brw.seekg(0, seekpos::begin);
auto b = co_await brw.read(1024);
std::string s = b ? std::move(*b).to_string() : "";

// 显式持久化到底层 I/O (推荐在作用域结束前显式调用)
co_await brw.flush();

API 概览

模板

  • template<block_read_write T> class block_read_writer;
    • 示例:block_read_writer<asco::io::file>

构造/析构

  • block_read_writer(T&& ioo)
  • block_read_writer(const T& ioo)
  • ~block_read_writer():析构时调用 flush() 尝试刷写缓冲

读写与缓冲

  • future<std::optional<buffer<>>> read(size_t nbytes)
    • 成功时返回数据;到达 EOF 返回 std::nullopt
    • 可被打断
  • future<void> write(buffer<> buf)
    • 仅更新内部活动缓冲区与写指针;不可打断
  • future<void> flush()
    • 将内部活动缓冲区自 buffer_start 起写入到底层 I/O;不可打断

定位与查询

  • size_t seekg(ssize_t offset, seekpos whence = seekpos::current)
  • size_t seekp(ssize_t offset, seekpos whence = seekpos::current)
  • size_t tellg() const noexcept
  • size_t tellp() const noexcept

行为与语义

  • 写入可见性
    • flush() 的写入对同一 block_read_writer 的后续 read() 可见
    • 调用 flush() 后方才写入到底层 I/O 对象
  • 读写指针
    • tellg/tellp 分别为读取进度与写入进度
    • seekg/seekp 相互独立,互不影响
  • 打断语义
    • read() 支持在等待过程中被打断;write()flush() 不支持打断
  • 析构行为
    • 析构函数会调用 flush() 刷写缓冲。

示例:覆盖写与稀疏写

// 初始内容
co_await brw.write(buffer("HelloWorld"));
co_await brw.flush();

// 覆盖中间 4 字节为 "ASCO"(总长度不变)
brw.seekp(6, seekpos::begin);
co_await brw.write(buffer("ASCO"));

// 形成 10 字节洞并在其后写 'X'
brw.seekp(20, seekpos::begin);
co_await brw.write(buffer("X"));

// 未 flush 时,通过 brw 读取可见:
brw.seekg(0, seekpos::begin);
std::string all;
while (auto part = co_await brw.read(4096)) all += std::move(*part).to_string();

co_await brw.flush(); // 持久化到底层

依赖与概念

  • 需包含:<asco/io/bufio.h><asco/io/buffer.h>
  • T 必须满足 block_read_write 概念(如 asco::io::file

注意事项

  • 非线程安全
  • flush() 前,其他对象(或进程)无法从底层 I/O 中看到你的写入