2013-12-21 22 views
0

我正在實現一個看起來像HTTP服務器的東西,設計是:對於已經建立的連接,我想重複使用它的幾個請求,所以我開始另一個閱讀任務async_read當一個請求完成時,它也啓動一個deadline_timer。如果在60秒內沒有輸入,定時器將被觸發並且連接將被破壞。令我感到困擾的是,在調用連接的析構函數之前,我們調用了設置爲async_read的回調函數。當任務擁有者被破壞時取消掛起的任務回調調用

所以,我的問題是,有沒有辦法取消掛起的閱讀任務,也就是說,在沒有調用回調函數的情況下破壞連接?

如果上述一般描述是不明確的,詳細的工作流程是如下(碼被附加在底部):

  1. cleanup()當一個請求完成被調用;
  2. 啓動定時器和cleanup()中的另一個閱讀任務;
  3. 如果時間不足,HandleTimeout()被調用,並且它調用stop();
  4. in stop(),乾淨的工作,並且之後,連接實例將被破壞。

但是,第4步之後,callback()函數將被調用,這是在AsyncRead()註冊,那麼,有沒有辦法取消的callback()調用?

代碼:

class Connection : public boost::enable_shared_from_this<Connection>, 
        private boost::noncopyable { 
public: 
    typedef Connection this_type; 

    void cleanup() { 
     timer_.expires_from_now(boost::posix_time::seconds(kDefaultTimeout)); 
     timer_.async_wait(boost::bind(&this_type::HandleTimeout, 
             shared_from_this(), 
             boost::asio::placeholders::error)); 
     AsyncRead(); 
    } 

    void AsyncRead() { 
     boost::asio::async_read(*socket_, in_, boost::asio::transfer_at_least(1), 
           boost::bind(&this_type::callback, 
              shared_from_this(), 
              boost::asio::placeholders::error)); 
    } 

    void callback(const boost::system::error_code& e) { 
     // ... 
    } 

    void HandleTimeout(const boost::system::error_code& e) { 
     if(e == boost::asio::error::operation_aborted) 
      LDEBUG << "The timeout timer is cancelled."; 
     else if(e) 
      LERROR << "Error occurred with the timer, message: " << e.message(); 
     else if(timer_.expires_at() 
        <= boost::asio::deadline_timer::traits_type::now()) { 
      LDEBUG << "Connection timed out, close it."; 
      stop(); 
     } 
    } 

    virtual void stop() { 
     connected_ = false; 
     socket_->close(); 

     connection_manager_.stop(shared_from_this()); 
    } 

private: 
    // ... 
    boost::asio::deadline_timer timer_; 
}; 

回答

1

有沒有乾淨的方式來做到這一點。只有這樣,才能保證隨時可以運行處理程序,如Connection::callback(),將不會被調用是要麼:

  • 停止處理io_service事件循環。
  • Destroyio_service,因爲io_service的析構函數會導致所有未解決的處理程序被銷燬。

在示例代碼,考慮Connection::callback()返回如果套接字不再開放:

void callback(const boost::system::error_code& error) 
{ 
    if (!socket_.is_open()) return; 
    // ... 
} 

還要注意的是error_code說法是不夠的,推斷是否已經發生超時。當調用socket::close()時,有可能Connection::callback()排隊調用error_codeboost::system::errc::success。因此,沒有取消操作。

+0

感謝您的回答,我只想確認是否有辦法做到這一點,現在答案似乎是「不」,是的,我需要一個解決方法來做到這一點。 –

+0

@KelvinHu你能否詳細說明你爲什麼需要不同的行爲?如果在'Connection'銷燬之前只調用'callback()',那麼考慮通過'boost :: weak_ptr'將'Connection'的生命期與回調處理程序解耦。這[回答](http://stackoverflow.com/a/18110168/1053968)演示了一個基本的弱指針綁定器,並且[[]](http://stackoverflow.com/a/19622084/1053968)明確地傳遞了'weak_ptr '給一個處理程序。在任何一種解決方案中,都會調用處理程序_will_,但只有在「連接」處於活動狀態時纔會調用「callback()」。 –