返回题库

协程异步读取

Coroutine Async Read

专题
Systems & Architecture / 系统与架构
难度
L2
来源
MyntBit

题目详情

高效网络 I/O 处理对高频交易系统最小化延迟和最大化吞吐至关重要。C++20 协程允许开发者使用同步式语法实现异步非阻塞逻辑,同时保持低延迟。

任务:实现 AsyncReader 类,使用 C++20 协程异步读取行情数据。read_async() 返回协程对象,在数据可用时恢复协程执行。支持多路并发读取和协程取消。

英文原题

Efficient network I/O handling is critical in high-frequency trading systems to minimize latency and maximize throughput while processing market data feeds. C++20 coroutines enable developers to implement asynchronous, non-blocking logic using synchronous syntax, facilitating high-performance event loops without the complexity of traditional callback mechanisms.
Task
Implement the AsyncReader class to perform asynchronous data reading using C++20 coroutines. Specifically, you must define the So

解析

问题分析

C++20 协程允许以同步写法表达异步逻辑。在量化系统中,使用协程进行异步文件 I/O 避免了回调地狱,同时允许在等待 I/O 完成时挂起协程以释放线程处理其他任务。

实现

#include <coroutine>
#include <experimental/io_context>

task<std::vector<char>> asyncReadFile(io_context& io, const std::string& path) {
    int fd = co_await io.open(path.c_str(), O_RDONLY);
    if (fd < 0) throw std::runtime_error("Failed to open");
    std::vector<char> buf(4096);
    ssize_t n = co_await io.read(fd, buf.data(), buf.size());
    buf.resize(std::max(0L, (long)n));
    co_await io.close(fd);
    co_return buf;
}
// 使用: auto data = co_await asyncReadFile(io, "/data/ticks.dat");

复杂度与边界

  • 时间复杂度:挂起/恢复 O(1),I/O 时间取决于底层
  • 空间复杂度:协程帧大小取决于局部变量(通常 < 1KB)
  • 边界条件:(1) 文件不存在抛异常 (2) 读取超过 4KB 需循环 (3) 协程在 io_context 析构前必须完成 (4) 不支持取消需通过超时实现

英文解析

Analysis

C++20 coroutines allow expressing asynchronous logic with synchronous-style code. In quantitative systems, using coroutines for async file I/O avoids callback hell while allowing the coroutine to suspend during I/O completion, freeing the thread to process other tasks.

Solution

#include <coroutine>
#include <experimental/io_context>

async_op<std::vector<char>> asyncReadFile(io_context& io, const std::string& path) {
    int fd = co_await io.open(path.c_str(), O_RDONLY);
    if (fd < 0) throw std::runtime_error("Failed to open");
    std::vector<char> buf(4096);
    ssize_t n = co_await io.read(fd, buf.data(), buf.size());
    buf.resize(std::max(0L, (long)n));
    co_await io.close(fd);
    co_return buf;
}
// Usage: auto data = co_await asyncReadFile(io, "/data/ticks.dat");

Complexity & Edge Cases

  • Time complexity: suspend/resume O(1), I/O time depends on underlying
  • Space complexity: Coroutine frame size depends on local variables (typically < 1KB)
  • Edge cases: (1) File not found throws exception (2) Reads exceeding 4KB require loop (3) Coroutines must complete before io_context destruction (4) Cancellation requires timeout implementation

Verification

Read multiple files concurrently via coroutines, verify all data loaded. Test exception propagation on file errors. Confirm thread utilization during I/O waits.

Key Considerations

Coroutines make async I/O readable without callback nesting. In backtesting frameworks, each data source (prices, fundamentals, trades) can be loaded as a coroutine, and the scheduler runs all concurrently on a single thread - maximizing I/O throughput while maintaining sequential code readability.