2016-07-28 34 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前端,並將其類型保存到函數對象中。