我正在使用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方法。但我迷失在模板类型中,不知道如何做到这一点。
我感谢任何帮助。 谢谢!
答案 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
或任何其他方法来创建您喜欢的功能对象。关键部分是将指向接收器前端的指针及其类型保存到函数对象中。