C++ ostreams 中的管道安全透明缓冲

问题描述 投票:0回答:0

我有一对程序,我正在编写许多短行数据,如

A=123 B=456 ...data...\n
到 cout 和其他文件输出流,每个大约 50 个字符长度。涉及到管道,所以我需要原子写入,我开始只是简单地刷新每一行写入,但现在刷新已经成为两个程序的主要瓶颈。

我希望我所有的输出流(包括 cout)将它们通过

<<
接收到的内容批处理到
PIPE_BUF
并刷新而不拼接单独的行(如果新内容会溢出缓冲区,则新内容不会被拼接) .我尝试做类似
std::cout.rdbuf()->pubsetbuf(new char[PIPE_BUF], PIPE_BUF - 200)
的事情,希望如果缓冲区很小,这将是实现的行为,但似乎调用没有做任何事情。

实际上,我想要以下代码示例对

cout
和我打开的任何其他 ostream 的影响;我可以调整一次流,但它必须在写入时透明地工作。

#include <iostream>
#include <limits.h> // PIPE_BUF
#include <random>
// #include <format>
// using std::format;
#include <fmt/format.h>
using fmt::format;

unsigned SAFE_BUF = PIPE_BUF - 200;
bool flushing = false;

int main() {
    unsigned pending = 0;
    for (int l = 0; l < 300'000; l++) {
        int A = rand() % 1000, B = rand() % 1000, L = rand() % 40, c = rand() % 26;
        std::string text = format("A={} B={} {}\n", A, B, std::string(L, 'a' + c));
        if (pending + text.size() >= SAFE_BUF) std::cout.flush(), pending = 0;
        std::cout << text, pending += text.size();
        if (flushing) std::cout.flush(), pending = 0;
    }
    return 0;
}
#!/bin/bash
rm -f test.log
for _ in 0 1 2 3 4 5 6 7; do ./writer >>test.log & done && wait
grep -q --invert-match "^A" test.log && echo MANGLED || echo OK
c++ buffer iostream
© www.soinside.com 2019 - 2024. All rights reserved.