我有一个vlog
类,负责打印程序中的所有日志消息。每个类都可以包含vlog.h
标头,然后使用以下代码记录数据:
{
std::lock_guard<std::mutex> lock(vlog::lock_log);
vlog::EVENT(host) << "hello" << " world!" << std::flush;
}
我想将上面的代码更改为这样的简单宏:
EVENT_LOG_C(host) << "hello" << " world!" << std::flush;
宏应首先调用lock_guard,然后将消息传递给vlog :: EVENT(host)对象。我该如何定义宏?
编辑:我希望整个日志msg(可能包含多个&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; <<
的每次使用都会调用静态对象,我无法将lock_guard放入vlog类本身。
答案 0 :(得分:4)
只需将std::lock_guard
填入宏中,但将其作为日志记录表达式的一部分:
#define EVENT_LOG_C(host) \
std::lock_guard<std::mutex>{vlog::lock_log}, vlog::EVENT(host)
其中的逗号运算符确保在右侧发生任何事件之前构造临时锁,并且它将一直存在直到分号结束。
你也可以通过让第一个operator <<
返回一个锁定代理来摆脱宏,然后转发每个跟随<<
直到表达式结束。
// Simple wrapper around the std::lock_guard to ease operator overloading
struct EventLogLocker {
EventLogLocker(std::mutex &mtx)
: lck{mtx} { }
std::lock_guard<std::mutex> lck;
};
// Perfect-forwarding operator << that hooks on the EventLogLocker
template <class T>
EventLogLocker const &operator << (EventLogLocker const &ell, T &&obj) {
// Log here
std::cout << std::forward<T>(obj);
return ell;
}
// operator << for iostream manipulators (these can't be deduced by the
// template above because they're overloaded for different stream types)
EventLogLocker const &operator << (
EventLogLocker const &ell,
std::ostream &(*manip)(std::ostream &)
) {
std::cout << manip;
return ell;
}
// Stub function, the important thing is to return an EventLogLocker by value
EventLogLocker EVENT_LOG_C(...) {
return {lock_log};
}
答案 1 :(得分:1)
您需要做的就是将互斥锁锁定在支持流操作的类的构造函数中,并在析构函数中释放互斥锁。
不需要宏。
例如;
namespace vlog
{
class EVENT
{
public:
EVENT() : event_lock(vlog::lock_log)
{
};
template<class T> EVENT &operator<<(const T &v)
{
std::cerr << v;
return *this;
};
private:
std::lock_guard<std::mutex> event_lock;
};
}
在上面,为了便于讨论,我假设您的日志记录将是std::cerr
,并且EVENT
的构造函数不接受任何参数。这很容易改变。
然后您需要做的就是
vlog::EVENT() << "hello" << "world" << std::flush;
本声明的工作原则是首先构建vlog::EVENT
。构造函数抓取互斥锁。然后在每次流操作期间继续抓取互斥锁。在语句的末尾(实际上是其中的表达式),vlog::EVENT
对象将被销毁,并且在销毁期间锁将被释放。
如果要将互斥锁锁定在多个语句上,只需将临时绑定到引用即可。这将对象的生命周期附加到引用的生命周期。或者构造一个命名对象。