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

How to stop all asynchronous sinks when using Boost.Log

本文关键字:接收器 异步 Log Boost      更新时间:2023-10-16

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

但是它采用特定的CCD_ 2类型。asynchronous_sink前端类具有接收器后端和队列策略的模板参数。

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

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

这确实是一个关于C++模板化数据结构的一般问题,由于Boost.Log中提供了接口,我需要解决这个问题。什么是好的数据结构来跟踪我添加到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库可以稍微简化这个过程。你可以创建一个信号,然后像这样将功能连接到它:

boost::signals2::signal< void() > stop_signal;
// For every asynchronous sink you do
stop_signal.connect([sink]()
{
    sink->flush();
    sink->stop();
});

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

stop_signal();

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