- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个应用程序,其中多个线程写入 std::cout
,我正在寻找一个简单的解决方案来防止发送到 std::cout
的数据被乱码。
例如,如果我有 2 个线程并且都输出:
std::cout << "Hello" << ' ' << "from" << ' ' << "thread" << ' ' << n << '\n';
我可能会看到这样的东西:
HelloHello from fromthread 2
thread 1
我想看到的是:
Hello from thread 2
Hello from thread 1
线条的显示顺序不是很重要,只要它们不混淆即可。
我想到了以下相当简单的实现:
class syncstream : public std::ostringstream {
public:
using std::ostringstream::ostringstream;
syncstream& operator<<(std::ostream& (*pf)(std::ostream&) ) { pf(*this); return *this; }
syncstream& operator<<(std::ios& (*pf)(std::ios&) ) { pf(*this); return *this; }
syncstream& operator<<(std::ios_base& (*pf)(std::ios_base&)) { pf(*this); return *this; }
template<typename T>
syncstream& operator<<(T&& token) {
static_cast<std::ostringstream&>(*this) << std::forward<T>(token);
return *this;
}
};
inline std::ostream& operator&&(std::ostream& s, const syncstream& g) { return s << g.str(); }
#define synced(stream) stream && syncstream()
抱歉宏。
所以,现在在我的线程中我可以做:
synced(std::cout) << "Hello" << ' ' << "from" << ' ' << "thread" << ' ' << n << '\n';
我写上面是因为我最初对§27.4.1的误解。但是,令人惊讶的是它的效果非常好。
我写了下面的测试用例:
void proc(int n) {
synced(std::cout) << "Hello" << ' ' << "world" << ' ' << "from" << ' ' << "thread" << ' ' << n << '\n';
}
int main() {
std::vector<std::thread> threads;
for(int n = 0; n < 1000; ++n) threads.push_back(std::thread(std::bind(proc, n)));
for(std::thread& thread: threads) thread.join();
return 0;
}
(完整版 here)并在我的系统上使用 g++ 4.8.3 和 clang++ 3.5.1(使用 libstdc++ 和 libc++)运行它。
测试是用 script 完成的,它运行测试用例 1000 次,生成 100 万行输出,然后解析输出以查找任何乱码行。
我不能让它不工作(即产生乱码)。
所以我的问题是:
为什么上述实现有效?
最佳答案
关于线程安全:从某种意义上说它是线程安全的不会引起数据竞争。但只要目标是其中之一标准流对象(std::cout
等),只要它们与 stdio 保持同步。这就是所有标准保证。和即便如此,您仍然可以得到交错的字符。
过去我不得不经常处理这个问题。我的解决方案有一直是一个包装类,带有指向实际的指针std::ostream
,和一个模板:
template <typename T>
SynchedOutput& operator<<( T const& obj )
{
if ( myStream != nullptr ) {
(*myStream) << obj;
}
return *this;
}
SynchedOutput
的构造函数然后获取一个互斥锁,并且析构函数释放它,所以你可以这样写:
SynchedOutput( stream, mutex ) << ...;
(在我的例子中,我从一个函数中返回临时值,并且在 C++11 及其移动语义之前这样做,所以我的代码有点多复杂;我必须支持复制,并跟踪计数拷贝,这样我就可以在最后一个被破坏时解锁。今天,只需实现移动语义,无需复制,如果你想返回来自函数的实例。))
这里的问题是确保每个人都使用相同的互斥量。一可能是让构造函数在一个std::map
在流对象的地址上建立索引。这个查找需要一个全局锁,所以如果流对象没有。真正的问题是确保当流被破坏时,互斥量将从映射中删除。
关于c++ - 将输出同步到 std::cout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28660602/
我想知道 cout<
这可能是一个初学者问题,了解 cout 的工作原理可能是这里的关键。如果有人可以链接到一个好的解释,那就太好了。 cout(&cout) 的地址. cout << &cout打印出 cout 的地址.
经过一整天的编码,我不小心写了 cout << "some text" << cout; 代替 cout << "some text" << endl; 现在它打印出一个内存地址。它指向什么? 最佳答
这与 difference-between-cout-x-and-cout-operator-x 有关问题,但还是有点不同... #include int main(){ std::cout
我是 C++ 的新手,最近我花了几天时间阅读有关指针的内容。我意识到下面的 2 段代码给我不同的结果,尽管它们看起来相同。 第一段代码: int a = 5; int* ptr = &a; cout
我尝试使用更短的语法并避免在任何地方使用 std::,所以我开始使用新的别名语法。在一些例子中,我看到人们这样使用它: using json = nlohmann::json; 并尝试使用 std::
这是我的头文件 #ifndef KINGDOM_H_ #define KINGDOM_H_ #include using namespace std; namespace sict{ cla
我经常遇到要将二维数组打印到屏幕或文件的情况。我的标准方法是这样的: for(int q=0; q #include void printNumber(int x) { std::cout
有一些 cout 语句,但第一个 cout 语句末尾的空格出现在第二个 cout 语句的开头。这是代码: #include int main() { using namespace std;
我在搞乱代码时遇到了这种相当模糊的行为,这是示例: #include using namespace std; int print(void); int main(void) { cout
我收到所有 cout 和 endl 的这些错误消息: main.cc:17:5: error: ‘cout’ was not declared in this scope main.cc:17:5:
这个问题在这里已经有了答案: What is the meaning of prepended double colon "::"? (9 个回答) 关闭 7 个月前。 有一个简单的代码,包含::操
我有下面的代码,我不太明白为什么结果恰好像下面这样: #include #include using namespace std; int main () { std::stringstre
在 C++ 中,当我在 .h 文件中声明自己的命名空间时,如下所示: namespace my_own { //... } 那么,如果我在命名空间 my_own 内部或外部声明 using s
背景 IIRC,来自 Release 2.0 C++ 将单字符常量存储为类型 char而不是 int .但是在 Release 2.0 之前声明如下 cout #include using name
Problem was in IDE I am using - CLion 1.2.4 gives incorrect output inside its own output window, sol
我知道有几个这样的拷贝,但到目前为止,没有一个对我有用。我正在尝试使用 g++ 在 Ubuntu 上编译一个非常简单的 C++ 程序,但它给了我范围错误。 #include using namesp
我在这里有一个难题,我无法解决,也没有在网上找到正确的答案: 我创建了一个带有清理路由的分离线程,问题是在我的 Imac 和 Ubuntu 9.1(双核)上。我无法正确取消空闲代码中的分离线程: #i
#include #include #include using namespace std; int main() { ofstream fout("test.txt"); f
我是一名优秀的程序员,十分优秀!