C++为数据记录定义宏
C++ #define macro for data logging
我有一个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)对象。如何定义宏?
编辑:我希望整个日志消息(可能由多个<<组成)是原子的。每次使用<<
都会调用静态对象,我不能将lock_guard放在vlog类本身中。
只需在宏中填充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};
}
您所需要做的就是将互斥锁锁定在支持流操作的类的构造函数中,并在析构函数中释放互斥。
不需要宏。
例如;
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
对象将被销毁,在销毁过程中,锁将被释放。
如果您想在多个语句上锁定互斥对象,只需将临时对象绑定到引用即可。将对象的生存期附加到引用的生存期。或者构造一个命名对象。
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 如何将自定义记录器与websocketpp一起使用?
- 如何声明和定义 Poco 记录器
- C++ 吉尼回归记录.对djinni_generated的未定义引用
- 如何让 doxygen 记录 .tcc 文件中定义的模板类?
- Boost Log-使用全局记录器时未定义的参考
- IIS 的自定义日志记录模块
- C++为数据记录定义宏
- 提升::日志 - 使用严重性和自定义过滤器属性记录?要使用的宏
- 如何让 Doxygen 记录在 C++ 文件中定义的类
- "演示项目::记录器" : "类"类型重新定义
- 是否可以在全局对象构造函数中进行打印/日志记录,或者这是一种未定义的行为?
- 在循环外定义std::istringstream记录
- 如何在C++中记录用户定义的POD结构