Reputation: 177
I am trying to implement async_connect() with a timeout.
async_connect_with_timeout(socket_type & s,
std::function<void(BoostAndCustomError const & error)> const & connect_handler,
time_type timeout);
When operation completes connect_handler(error)
is called with error
indicating operation result (including timeout).
I was hoping to use code from timeouts example 1.51. The biggest difference is that I am using multiple worker threads performing io_service.run().
What changes are necessary to keep the example code working?
My issues are:
When calling :
Start() {
socket_.async_connect(Handleconnect);
dealine_.async_wait(HandleTimeout);
}
HandleConnect()
can be completed in another thread even before async_wait()
(unlikely but possible). Do I have to strand
wrap Start()
, HandleConnect()
, and HandleTimeout()
?
What if HandleConnect()
is called first without error, but deadline_timer.cancel()
or deadline_timer.expires_from_now()
fails because HandleTimeout()
"have been queued for invocation in the near future"? Looks like example code lets HandleTimeout()
close socket. Such behavior (timer closes connection after we happily started some operations after connect) can easily lead to serious headache.
What if HandleTimeout()
and socket.close()
are called first. Is it possible to HandlerConnect()
be already "queued" without error? Documentation says: "Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted
error". What does "immediately" mean in multithreading environment?
Upvotes: 0
Views: 824
Reputation: 15075
You should wrap with strand each handler, if you want to prevent their parallel execution in different threads. I guess some completion handlers would access socket_
or the timer, so you'll definitely have to wrap Start()
with a strand as well. But wouldn't it be much more simple to use io_service-per-CPU model, i.e. to base your application on io_service
pool? IMHO, you'll get much less headache.
Yes, it's possible. Why is it a headache? The socket gets closed because of a "false timeout", and you start re-connection (or whatever) procedure just as if it were closed due to a network failure.
Yes, it's also possible, but again, it shouldn't cause any problem for correctly designed program: if in HandleConnect
you try to issue some operation on a closed socket, you'll get the appropriate error. Anyway, when you attempt to send/receive data you don't really know the current socket/network status.
Upvotes: 1