提问人:elbrunovsky 提问时间:3/19/2023 最后编辑:elbrunovsky 更新时间:3/19/2023 访问量:36
c++ ostreams 中的管道安全透明缓冲
Pipe-safe transparent buffering in c++ ostreams
问:
我有一对程序,我在其中编写了许多短行数据,例如 cout 和其他文件输出流,每个程序大约有 50 个字符长。涉及管道,所以我需要原子写入,我从简单地刷新每一行写入开始,但现在刷新已成为两个程序的主要瓶颈。A=123 B=456 ...data...\n
我希望我的所有输出流(包括 cout)在不拼接单个行的情况下批处理它们接收到的内容并刷新(如果新内容会溢出缓冲区,则新内容不会被拼接)。我尝试做一些事情,比如如果缓冲区很小,希望这将是实现的行为,但似乎调用没有做任何事情。<<
PIPE_BUF
std::cout.rdbuf()->pubsetbuf(new char[PIPE_BUF], PIPE_BUF - 200)
实际上,我希望以下代码示例对我打开的任何其他 ostreams 都有效果;我可以调整一次流,但它必须在写入时透明地工作。cout
#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
答: 暂无答案
评论