我有一个通过cout和CERR写入控制台的OpenMP线程。 当然,这并不安全,因为输出可以交错。 我可以做类似
#pragma omp critical(cerr)
{
cerr << "my variable: " << variable << endl;
}
这将是更好,如果能有一个线程安全的版本替换CERR,类似的做法在Valgrind的DRD手动解释( http://valgrind.org/docs/manual/drd-manual.html#drd-manual.effective-使用 ),它涉及到从获得的std :: ostreambuf类。 理想的情况下在最后我只想用我自己的螺纹CERR更换CERR,如简单地说:
tcerr << "my variable: " << variable << endl;
因为它遇到一个“ENDL”这样的类可以尽快打印到控制台。 我不介意,如果从不同的线程线交错,但各行应该从一个线程只来。
我真的不明白怎么这一切流于C ++的作品,实在是太复杂了。 有没有人这样的类或能告诉我如何创建用于该目的这样一个班?
正如其他人所指出的,在C ++ 11 std::cout
是线程安全的。
但是如果你使用它像
std::cout << 1 << 2 << 3;
用不同的线程,输出仍然可以交错,因为每个<<
是一个新的函数调用可以通过另一个线程的任何函数调用preceeded。
为了避免没有交错#pragma omp critical
-这将锁定一切-你可以做到以下几点:
std::stringstream stream; // #include <sstream> for this
stream << 1 << 2 << 3;
std::cout << stream.str();
三个电话写123到流都发生在只有一个线程到本地,非共享的对象,因此不会受到任何其他线程。 那么,只有一个调用共享输出流std::cout
,其中123项已经是固定的顺序,因此不会搞的一团糟。
您可以使用类似的字符串生成器的方法。 创建一个非模板类:
- 提供模板化的
operator<<
插入到该对象 - 在内部构建成
std::ostringstream
- 转储上破坏的内容
粗糙的方法:
class AtomicWriter {
std::ostringstream st;
public:
template <typename T>
AtomicWriter& operator<<(T const& t) {
st << t;
return *this;
}
~AtomicWriter() {
std::string s = st.str();
std::cerr << s;
//fprintf(stderr,"%s", s.c_str());
// write(2,s.c_str(),s.size());
}
};
用于:
AtomicWriter() << "my variable: " << variable << "\n";
或在更复杂的情况:
{
AtomicWriter w;
w << "my variables:";
for (auto & v : vars) {
w << ' ' << v;
}
} // now it dumps
您将需要添加更多的重载如果你想操纵器,您可以用write
优于fprintf
在析构函数中的原子写 ,或std::cerr
,你可以概括,以使目标被传递给构造( std::ostream
/文件描述符/ FILE*
),
我没有足够的信誉发表评论,但我想我的后除了在AtomicWriter类支持的std :: ENDL,并允许除性病::法院要使用其他流。 这里是:
class AtomicWriter {
std::ostringstream st;
std::ostream &stream;
public:
AtomicWriter(std::ostream &s=std::cout):stream(s) { }
template <typename T>
AtomicWriter& operator<<(T const& t) {
st << t;
return *this;
}
AtomicWriter& operator<<( std::ostream&(*f)(std::ostream&) ) {
st << f;
return *this;
}
~AtomicWriter() { stream << st.str(); }
};
你可以通过继承做到这一点std::basic_streambuf
,并覆盖正确的功能,使其线程安全的。 然后使用这个类为您的流对象。