实际上,我正在寻找一种在我的C++中进行异步和线程安全日志记录的方法。
我已经探索过线程安全的日志记录解决方案,如log4cpp、log4cxx、Boost:log或rlog,但它们似乎都使用了互斥锁。据我所知,互斥是一种同步解决方案,这意味着所有线程在尝试写入消息时都会被锁定,而其他线程则会这样做。
你知道解决方案吗?
发布于 2011-11-16 19:19:30
我认为你的说法是错误的:使用互斥不一定等同于同步解决方案。是的,Mutex是用于同步控制的,但它可以用于许多不同的事情。例如,我们可以在生产者、消费者队列中使用互斥锁,同时日志记录仍在异步进行。
老实说,我没有研究过这些日志库的实现,但是应该可以创建一个异步附加器(对于像lib这样的log4j ),记录器写入生产者消费者队列,而另一个工作线程负责写入文件(甚至委托给另一个附加器),以防它没有提供。
编辑:刚刚在log4cxx中做了一个简单的扫描,它提供了一个AsyncAppender,它做了我建议的事情:缓冲传入的日志事件,并异步委托给附加的附加器。
发布于 2011-11-16 19:04:03
我会重新注释,通过只使用一个线程来记录日志来避免这个问题。为了将必要的数据传递到日志,可以使用无锁fifo队列(只要生产者和消费者严格分离,并且每个角色只有一个线程,那么线程就是安全的--因此,每个生产者需要一个队列。)
快速解锁队列示例如下:
queue.h e.h:
#ifndef QUEUE_H
#define QUEUE_H
template<typename T> class Queue
{
public:
virtual void Enqueue(const T &element) = 0;
virtual T Dequeue() = 0;
virtual bool Empty() = 0;
};
杂交队列.h:
#ifndef HYBRIDQUEUE_H
#define HYBRIDQUEUE_H
#include "queue.h"
template <typename T, int size> class HybridQueue : public Queue<T>
{
public:
virtual bool Empty();
virtual T Dequeue();
virtual void Enqueue(const T& element);
HybridQueue();
virtual ~HybridQueue();
private:
struct ItemList
{
int start;
T list[size];
int end;
ItemList volatile * volatile next;
};
ItemList volatile * volatile start;
char filler[256];
ItemList volatile * volatile end;
};
/**
* Implementation
*
*/
#include <stdio.h>
template <typename T, int size> bool HybridQueue<T, size>::Empty()
{
return (this->start == this->end) && (this->start->start == this->start->end);
}
template <typename T, int size> T HybridQueue<T, size>::Dequeue()
{
if(this->Empty())
{
return NULL;
}
if(this->start->start >= size)
{
ItemList volatile * volatile old;
old = this->start;
this->start = this->start->next;
delete old;
}
T tmp;
tmp = this->start->list[this->start->start];
this->start->start++;
return tmp;
}
template <typename T, int size> void HybridQueue<T, size>::Enqueue(const T& element)
{
if(this->end->end >= size) {
this->end->next = new ItemList();
this->end->next->start = 0;
this->end->next->list[0] = element;
this->end->next->end = 1;
this->end = this->end->next;
}
else
{
this->end->list[this->end->end] = element;
this->end->end++;
}
}
template <typename T, int size> HybridQueue<T, size>::HybridQueue()
{
this->start = this->end = new ItemList();
this->start->start = this->start->end = 0;
}
template <typename T, int size> HybridQueue<T, size>::~HybridQueue()
{
}
#endif // HYBRIDQUEUE_H
发布于 2011-11-16 19:08:31
如果我没有弄错您的问题,那么您关心的是在记录器的临界区中执行I/O操作(可能是写入文件)。
Boost:log可以让你定义一个自定义的编写器对象。您可以定义操作符()来调用异步I/O或将消息传递到日志记录线程(正在执行I/O)。
http://www.torjo.com/log2/doc/html/workflow.html#workflow_2b
https://stackoverflow.com/questions/8150249
复制相似问题