2016-07-28 101 views
0

我正在使用Boost.Log异步接收器(请参阅Asynchronous sink frontend)。要正确关机,必须正常停止并冲洗记录到异步接收器的馈送。核心具有添加和移除汇的方法,但似乎没有办法让客户获得汇或访问它们。该文档具有stop_logging方法,如何在使用Boost.Log时停止所有异步接收器

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类型。前端类具有用于接收器后端和排队策略的模板参数。

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

我都会有几种不同类型的汇,所以我想有持有它们的通用容器,这样我就可以简单的叠代,并呼吁stop_logging每个沉在容器中。

这实际上是一个关于C++模板化数据结构的常见问题,由于Boost.Log提供的接口,我需要解决这些问题。什么是一个好的数据结构来跟踪我添加到Boost.Log内核的异步接收器?我需要一个,所以我可以在关机时致电stop_logging

我的第一个简单的方法是有一个向量boost::any对象。但是这很麻烦,不雅。我怀疑一个合理的方法是使用lambda方法调用stop_logging的函数对象的向量。但是我迷失在模板类型中,不知道如何去做。

我很感激任何帮助。 谢谢!

回答

1

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

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或任何其他手段来创建对象你喜欢的功能。重要的部分是将指针保存到sink前端,并将其类型保存到函数对象中。