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

How to stop all asynchronous sinks when using Boost.Log

我正在使用 Boost.Log 异步接收器(参见 Asynchronous sink frontend)。要正确关闭,必须优雅地停止并将记录馈送刷新到异步接收器。核心有添加和删除接收器的方法,但似乎没有办法让客户端获取或访问接收器。文档有一个 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();
}

但它需要特定的 sink_t 类型。 asynchronous_sink 前端 class 具有用于接收器后端和排队策略的模板参数。

  template<typename SinkBackendT, 
           typename QueueingStrategyT = unbounded_fifo_queue> 
    class asynchronous_sink;

我会有几种不同类型的接收器,所以我想要一个通用容器来容纳它们,这样我就可以简单地迭代它并为容器中的每个接收器调用 stop_logging

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

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

感谢您的帮助。 谢谢!

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

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 或任何其他方式来创建您喜欢的函数对象。关键部分是将指向接收器前端的指针及其类型保存到函数对象中。