问题
In the recent development of my project have I used std::future
with async_read_some
so that caller, say user thread, can wait for specific duration on asynchronous I/O and appear like a synchronous procedure. But call to get std::future object async_read_some function yields never returns in case that the remote connecting peer corrupts. It seems that system error in asynchronous operation is not propagated as stated at all.
std::future<size_t> result=socket.async_read_some(boost::asio::buffer(data, size), boost::asio::use_future);
std::future_status status=result.wait_for(std::chrono::millisecond(1000));
switch(status){
case std::future_status::ready:
try{
bytes=result.get(); /* never returns in case of peer disconnection */
}catch(std::system_error & error){
/* print something only if error is caught */
}
break;
case std::future_status::timeout:
...
case std::future_status::deferred:
...
};
when program runs in according scenario, the process "sinks" - it appears exactly like there is deadlock in asio implementation. A trace stops in implementation of std::future::get()
/// Wait for the state to be ready and rethrow any stored exception
__result_type
_M_get_result() const
{
_State_base::_S_check(_M_state);
_Result_base& __res = _M_state->wait();
if (!(__res._M_error == 0))
--> rethrow_exception(__res._M_error); <-- //deepest trace with available source
return static_cast<__result_type>(__res);
}
After investigating into documentation, I found very few words
std::future<std::size_t> my_future = my_socket.async_read_some(my_buffer, boost::asio::use_future);
The initiating function (async_read_some in the above example) returns a future that will receive the result of the operation. If the operation completes with an error_code indicating failure, it is converted into a system_error and passed back to the caller via the future.
However, there is NOTHING my program catches around result.get()
.
PS: linux 3.8.0-37-generic #53~precise1-Ubuntu SMP Wed Feb 19 21:39:14 UTC 2014 i686 i686 i386 GNU/Linux
回答1:
Are you doing that in the thread that performs io_service.run()
?
If yes then std::future_status status=result.wait_for(std::chrono::millisecond(1000));
will block because no result can be received until the io_service returns to it's event loop to be able to check for new data there.
So using the future
would only make sense if you access it from another thread (which can block while Boosts io_service can do the work).
If you want to do everything in the same thread you will be required to work in an asynchronous style, e.g. with the callbacks that are invoked when the operation completes.
来源:https://stackoverflow.com/questions/22627382/program-to-read-asynchronously-in-boost-asio-with-c11-future