Boost.Asio:关闭套接字并停止计时器并调用处理程序的正确方法

时间:2012-07-11 12:15:58

标签: c++ boost boost-asio

假设我有类X封装了asio :: ip :: tcp :: socket和deadline_timer。如果连接速度太慢,则用于断开连接。这是X:

class X
{
public:
 typedef boost::function<void(const error_code&)> Handler;
 void f(Handler);
 void close();
private:
 void on_connected(const error_code&);
 void on_timeout(const error_code&);
 void on_work_is_done(const error_code&);
 Handler h_;
 socket s_;
 deadline_timer t_;
};

函数f做了一些工作(发送,接收,...)然后调用这样的处理程序:

void on_work_is_done(const error_code& e)
{
 //swapping handlers to release handler after function exits
 Handler h;
 h.swap(h_);
 h(e);
}

在此期间,计时器t正在滴答作响。所以我的问题是: 什么是让X :: close的好方法? close()必须关闭套接字并停止计时器t,它必须调用处理程序h似乎非常自然,但只有在所有异步操作(在s和t上)被取消之后。如果没有计时器,那么问题就解决了:

void X::close() { s.close(); }

将取消异步操作并使用err == operation_aborted调用on_work_is_done(),这将传递给处理程序,然后处理程序将被释放。一切都好。但由于有2个对象,并且每个对象可能都有一些待处理的异步操作,因此问题似乎更复杂。因为如果我们这样做

void X::close() 
{
 s.close(); 
 t.cancel();
}

将调用两个处理程序(on_work_is_done,on_timeout),但我们可以从最后调用的处理程序中调用swapped handler_(err)。 有一些直截了当的解决方案吗?

我看到以下方法:

a)添加size_t counter_,它将在X :: close()中设置为2,每个处理程序将减少1.因此,使counter_ == 0的处理程序将调用handler_(operation_aborted);

b)运行t.cancel()和on_timeout(err)如果err == operation_aborted调用s.cancel,则从on_work_is_done()调用handler_(operation_aborted)

或者整个方法都很糟糕,还有更好的方法吗?

0 个答案:

没有答案