使用Boost.Log时如何停止所有异步接收器

时间:2016-07-28 04:37:11

标签: c++ logging lambda stl boost-log

我正在使用Boost.Log异步接收器(参见Asynchronous sink frontend)。要正确关闭,必须正常停止并刷新记录到异步接收器的馈送。核心有添加和删除接收器的方法,但似乎没有办法让客户端获取接收器或访问它们。该文档具有cats方法,

stop_logging

但它需要特定的void stop_logging(boost::shared_ptr< sink_t >& sink) { boost::shared_ptr< logging::core > core = logging::core::get(); // Remove the sink from the core, so that no records are passed to it core->remove_sink(sink); // Break the feeding loop sink->stop(); // Flush all log records that may have left buffered sink->flush(); sink.reset(); } 类型。 asynchronous_sink前端类具有接收器后端和排队策略的模板参数。

sink_t

我将有几种不同类型的接收器,所以我希望有一个容纳它们的通用容器,所以我可以简单地迭代它并为容器中的每个接收器调用 template<typename SinkBackendT, typename QueueingStrategyT = unbounded_fifo_queue> class asynchronous_sink;

由于Boost.Log中提供的接口,这是我需要解决的C ++模板化数据结构的一般问题。用于跟踪我添加到Boost.Log核心的异步接收器的良好数据结构是什么?我需要一个,所以我可以在关机时调用stop_logging

我的第一个简单方法是使用stop_logging个对象的向量。但这是相当繁琐和不优雅的。我怀疑一个合理的方法是拥有一个函数对象的向量,这些函数对象是调用boost::any的lambda方法。但我迷失在模板类型中,不知道如何做到这一点。

我感谢任何帮助。 谢谢!

1 个答案:

答案 0 :(得分:2)

最直接的解决方案是拥有一个带有函数对象的容器,如您所建议的那样。例如:

std::vector< std::function< void() > > stop_functions;

// For every asynchronous sink you add
stop_functions.emplace_back([sink]()
{
    sink->flush();
    sink->stop();
});

在此示例中,sink可以是指向您恰好添加到日志记录核心的任何asynchronous_sink实例的指针。当您的应用程序终止时,您只需调用容器中的所有已保存函数:

for (auto& stop : stop_functions)
    stop();

但是,有一个Boost.Signals2库allows可以简化这个过程。您可以创建一个信号,然后将功能连接到它:

boost::signals2::signal< void() > stop_signal;

// For every asynchronous sink you do
stop_signal.connect([sink]()
{
    sink->flush();
    sink->stop();
});

然后通过调用信号,您将调用每个连接的函数对象,有效地停止每个接收器。

stop_signal();

在任何一种情况下,您都可以使用std::bind或任何其他方法来创建您喜欢的功能对象。关键部分是将指向接收器前端的指针及其类型保存到函数对象中。