提问人:digito_evo 提问时间:12/27/2022 更新时间:1/18/2023 访问量:192
如何有效地使用 std::osyncstream 对象?
How to efficiently use the std::osyncstream objects?
问:
在 cppreference 上有一个关于如何使用类的示例代码:std::osyncstream
#include <string_view>
#include <syncstream>
#include <iostream>
#include <thread>
void worker(const int id, std::ostream &os) {
std::string_view block;
switch (id) {
default: [[fallthrough]];
case 0: block = "██"; break;
case 1: block = "▓▓"; break;
case 2: block = "▒▒"; break;
case 3: block = "░░"; break;
}
for(int i = 1; i <= 50; ++i) {
os << block << std::flush;
}
os << std::endl;
}
int main() {
std::cout << "Synchronized output should not cause any interference:" << std::endl;
{
auto scout1 = std::osyncstream{std::cout};
auto scout2 = std::osyncstream{std::cout};
auto scout3 = std::osyncstream{std::cout};
auto scout4 = std::osyncstream{std::cout};
auto w1 = std::jthread{worker, 0, std::ref(scout1)};
auto w2 = std::jthread{worker, 1, std::ref(scout2)};
auto w3 = std::jthread{worker, 2, std::ref(scout3)};
auto w4 = std::jthread{worker, 3, std::ref(scout4)};
}
std::cout << "\nLack of synchronization may cause some interference on output:" << std::endl;
{
auto w1 = std::jthread{worker, 0, std::ref(std::cout)};
auto w2 = std::jthread{worker, 1, std::ref(std::cout)};
auto w3 = std::jthread{worker, 2, std::ref(std::cout)};
auto w4 = std::jthread{worker, 3, std::ref(std::cout)};
}
}
现在我的问题很简单:为每个单独的执行线程使用这些对象的最有效(就运行时速度而言)方法是什么?在上面的示例中,它们是在调用站点构造的,然后通过引用传递给线程(顺便说一句,如何绑定到类型的对象?另一方面,在我的小程序中,我尝试在每个函数中构造一个单独的本地对象,然后写入它,这工作正常。这样我就不必通过引用函数(如上面的代码)来传递它们。std::ostream &os
std::osyncstream{std::cout}
std::osyncstream{std::cout}
那么创建这些对象的规则是什么呢?我们需要创建多少个,在哪里创建?我目前有一个小程序,它同时运行两个不相关的 s,这两个 s 都按顺序调用多个函数(每个函数 8 个),这些函数尝试写入 .我需要防止文本交错。现在,这 16 个函数中的每一个都通过 .添加这些对象后,可执行文件的大小翻了一番。因此,这似乎根本不是最佳方法。我是否应该在每个函数中有一个对象,然后通过引用将其传递给按顺序运行的 8 个内部函数?std::jthread
jthread
std::cout
cout
std::osyncstream{std::cout} << "like this\n";
osyncstream
std::osyncstream
jthread
答:
顺便说一句,如何绑定到类型的对象?
std::ostream &os
std::osyncstream{std::cout}
与对 TYPE 的任何引用绑定到表达式的方式相同Base
Derived
那么创建这些对象的规则是什么呢?我们需要创建多少个,在哪里创建?
每个单独的对象都包含一个单独的(以及每个对象保存的一堆其他状态),该状态包含一个单独的堆分配的字节缓冲区(加上几个标志和指向 cout 互斥锁的指针)。
因此,如果您总是使用临时临时 (),则可能会破坏并重新创建所有这些状态和所有这些缓冲区,这可能是不必要的。原始代码通过为每个线程分配一个线程来避免这种徒劳的工作。osyncstream
syncbuf
ostream
std::osyncstream{std::cout} << "like this\n";
osyncstream
评论