2016-02-19 61 views
1

在我們的產品,我們擁有可以基本上這個功能簡化代碼:從處理程序或處理程序中刪除boost :: asio定時器是否安全?

#include <boost/asio/steady_timer.hpp> 
#include <functional> 

void DelayedCall(
    boost::asio::io_service& io, 
    boost::asio::steady_timer::duration delay, 
    std::function<void()> f) 
{ 
    auto timer = std::make_shared<boost::asio::steady_timer>(io, delay); 
    timer->async_wait(
     [timer, f](boost::system::error_code const&) 
     { 
      // Probably it's ok to do even this: 
      //timer.reset(); 
      f(); 
     } 
    ); 
} 

假設io對象具有簡單的全球壽命。

正如你可以看到計時器對象將在處理器的析構函數被破壞。

當這個問題出現在我的腦海裏時,我提防了定時器中的一些引用執行了處理程序,反之亦然。我知道定時器析構函數將調用所有異步等待處理程序上的cancel,但這與處理程序已經執行並且無法取消無關。

現在我覺得計時器對象只是post()小號處理程序io_service當時間一到,所以定時器和處理相互獨立。儘管如此,快速嘗試調查asio源代碼失敗,所以我仍然不確定我們的代碼是否正確。

我沒有找到文檔中既不here也不here任何相關信息。

回答

1

這是安全的,所有的I/O對象明確界定。


Boost.Asio的已努力通過shared_ptr物體結合成以支持使用shared_ptr來擴展對象的生命週期,例如steady_timer,至少只要是異步操作的序列處理程序。 documentation說明:

允許程序通過使用shared_ptr<>簡化其資源管理。其中對象的生命週期依賴於一個連接(或異步操作的一些其他序列)的壽命,一個shared_ptr到對象將被綁定到處理程序與它相關聯的所有異步操作。

爲了支持這一點,啓動函數接受處理程序的值,Boost.Asio負責維護處理程序的有效性。實現可以使處理器的副本和所有副本都保證被毀滅的處理程序被調用

  • io_service

    • 立即被銷燬
    • 擁有該處理器的io_service::service是關機通過shutdown_service()

    requirements on asynchronous operations documentation狀態:

    啓動函數的參數將被視爲如下:

    - 如果參數聲明爲const引用或by-value,則在啓動函數完成後,程序不需要保證參數的有效性。該實現可以創建參數副本,並且所有副本將在調用處理程序後立即銷燬。

  • +0

    我相信你,但你的引文與我的問題無關。他們都談論一個'io_service'對象,而不是定時器。我沒有在定時器文檔中找到任何[這裏](http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/steady_timer.html),也沒有[http: //www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/WaitableTimerService.html)。 – magras

    +0

    @magras也許我誤解了這個問題。前者的引用是爲了強調Asio已經被開發來支持你的代碼使用的資源管理類型。鏈接的材料一起定義了處理程序何時被銷燬,並且在您的情況下,這會定義何時會銷燬「steady_timer」。 –

    +0

    我的不好。我試圖澄清問題。如果你仍然對它感興趣,請檢查編輯。 – magras

    0

    shared_ptr參考計數器變爲0時,計時器將被銷燬,當shared_ptr所屬關閉時將會被銷燬。所以以這種特殊方式使用它是安全的。但是,請注意,如果通過引用[&timer]或通過移動[timer = std::(move(timer))]改變你通過定時器拉姆達,例如方式的代碼會崩潰,因爲沒有shared_ptr參考抄襲遞增,計時器會在你處理範圍的出口被破壞。

    +2

    定時器在突出的等待操作中被破壞是安全的。未完成的等待操作將在計時器的析構函數中隱式取消。這允許通過引用來捕獲是安全的,但可能具有不希望的效果。另一方面,由於lambda捕獲的副作用和'shared_ptr :: operator - >()'之間的順序次序,動態捕獲會調用未定義的行爲。 –

    +0

    @Tanner,謝謝,那更乾淨。稍後我會發布我的asio源代碼調查結果。 – magras

    相關問題