如何创建一个新类来继承 ostream 并将其用作 cout 但带有锁定
How can I create a new class to inherit ostream and use it as cout but with lock
我使用 std::cout 在控制台上打印日志。由于该程序是多线程的,如果我在cout之后使用多个"<<"操作,打印结果将是无序的。
例如,如果一个线程执行cout<< "A" << "B" << endl;
则另一个线程可能在 A 和 B 之间执行cout << "C";
。结果将是"ACB"。
因此,我将编写一个新类来继承ostream
(实际上是basic_ostream<char, char_traits<char>>
(,并在初始化 cout 时添加一个锁,因此打印输出应遵循正确的顺序。
一种选择是创建一个类,该类保存对流的引用,但在其整个生命周期中保持锁。下面是一个简单的示例:
#include <iostream>
#include <mutex>
struct LockedOstream {
std::lock_guard<std::mutex> lg_;
std::ostream& os_;
LockedOstream(std::mutex& m, std::ostream& os)
: lg_{m}
, os_{os}
{ }
std::ostream& stream() const { return os_; }
};
int main()
{
std::mutex m;
LockedOstream(m, std::cout).stream() << "foo " << "barn";
// ^ locked now ^ unlocked now
}
只要构成单个输出"单位"的所有打印都发生在同一语句中,这就可以工作。
编辑:实际上,继承版本比我最初预期的要好得多:
#include <iostream>
#include <mutex>
class LockedOstream : public std::ostream {
static std::mutex& getCoutMutex()
// use a Meyers' singleton for the cout mutex to keep this header-only
{
static std::mutex m;
return m;
}
std::lock_guard<std::mutex> lg_;
public:
// Generic constructor
// You need to pass the right mutex to match the stream you want
LockedOstream(std::mutex& m, std::ostream& os)
: std::ostream(os.rdbuf())
, lg_{m}
{ }
// Cout specific constructor
// Uses a mutex singleton specific for cout
LockedOstream()
: LockedOstream(getCoutMutex(), std::cout)
{ }
};
int main()
{
LockedOstream() << "foo " << "barn";
// ^ locked now ^ unlocked now
}
顺便说一句:
-
using namespace std;
被广泛认为是不良做法,并且 - 我不是
std::endl
的忠实粉丝也
(虽然后者有时会引起争议,但至少知道并做出明智的选择是个好主意(。
您可以定义自己的函数
template<typename... Ts>
void locked_print(std::ostream& stream, Ts&&... ts)
{
static std::mutex mtx;
std::lock_guard<std::mutex> guard(mtx);
(stream << ... << std::forward<Ts>(ts));
}
当您想确保它是独家的时,您可以像locked_print(std::cout, 1, 2, "bar");
由于outstream << x1 << x2 << ...
是多个函数调用,因此除了锁定所有内容直到销毁相同的外流之外,您无法在内部执行此操作。调用约束时,只需强制约束:
{
std::lock_guard<std::mutex> guard(global_mutex);
// your print here
}
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 如何找到锁定Linux futex的C++行
- G锁定铸造到基础上会释放模拟行为
- std::cout.imbue()多重调用
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 为什么在C的循环中使用printf的Rust代码不显示输出,而在C++的循环中显示std::cout
- 如何检查线程是否锁定
- 如何在C++中找到active directory中禁用和锁定的窗口帐户
- 我应该在锁定TBitmap画布后解锁它吗
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 在 COUT 语句中使用 COUT 调用函数
- GCC 4.8.2 自动矢量化由于 cout 而失败
- std::cout输出int时出现编译错误
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- C++ Setter/Getter,cout 工作,printf 失败
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 如何创建一个新类来继承 ostream 并将其用作 cout 但带有锁定
- boost::scoped_lock 似乎没有锁定 std::cout
- IOstream线程安全,必须将cout和cerr分开锁定