Re: [Boost-users] [asio] sync receive_from with timeout
Ha this is exactly the problem I ran into not two days ago I agree it would be nice if there was a timeout for the library: I used to following: //Oh throw a sleep in there: while(!timeout.elapsed()) { boost::system::error_code ec; boost::asio::socket_base::non_blocking_io command(true); socket.io_control(command); bytesRead = _socket->read_some(boost::asio::buffer(data, dataBufferSize), ec); if(error&&boost::asio::error::would_block!=error) { //there is some other error the client has disconnected; } else { //I must have got some data or theres no data yet check bytesRead for that } boost::this_thread::sleep( boost::posix_time::milliseconds(100)); } No extra threads necessary. Stephan Menzel-3 wrote:
Is the subject Jehova enough for you? ;-)
Great.
Well, I haven't raised the subject so far but I'd certainly like to do so now. For years now I am not only a user but also an admirer of boost asio. Something that has always puzzled me however is, why a timeout functionality which is something very common and essential for sync IO just doesn't seem to be there.
I think there are cases where syncronous IO is a better way to go and no async approach is sensible. In my case this is a collection of static functions that do UDP communication and therefore have to be sync because I just want them to be able to return and throw exceptions and be able to be called from anyone at any time.
As always when I stumble across the asio/timeout problem I start googling around. When people raise the topic here they are usually pointed to an answer Chris Kohlhoff gave to someone asking that:
http://lists.boost.org/Archives/boost/2007/04/120339.php
... which is good for tcp and works alright even though in my opinion it leaves the question why it has to be so compilicated to do something so basic. IMHO sync IO is all but pointless without a timeout.
Anyway, I started to turn this into a UDP version and ended up with something very similar:
inline void set_result(boost::optionalboost::system::error_code* a, boost::system::error_code b) { a->reset(b); };
template <typename MutableBufferSequence> void udp_read_with_timeout(boost::asio::ip::udp::socket& sock, int tmo, boost::asio::ip::udp::endpoint &endpoint, const MutableBufferSequence& buffers) {
boost::optionalboost::system::error_code timer_result; boost::asio::deadline_timer timer(sock.io_service()); timer.expires_from_now(boost::posix_time::seconds(tmo)); timer.async_wait(boost::bind(set_result, &timer_result, _1));
boost::optionalboost::system::error_code read_result; sock.async_receive_from(buffers, endpoint, boost::bind(set_result, &read_result, _1));
sock.io_service().reset(); while (sock.io_service().run_one()) { if (read_result) timer.cancel(); else if (timer_result) sock.cancel(); }
if (*read_result) throw boost::system::system_error(*read_result); };
So now I started to go ahead with that but I had to notice two things. First, the performance impact is massive to a point that forces me to reconsider. Second, when I use that in a multithreaded environment the whole thing seems to block in some threads randomly. I have made test program where I have multiple threads using that method, just sending an UDP request to a server and waiting for an answer using this function. In one thread everything is slow but continously running. In more than one thread it blocks for up to 5 or 6 seconds every few (10-20) runs for no visible reason. In my scenario all those threads share a socket protected by a mutex so if one of them blocks all will be halted.
So I come to think this is not a good way to handle the problem. Does anyone have some thoughts on that? May this be a bug in asio (1.38) or perhaps in my function? Or is there a better way to do sync UDP IO with a timeout functionality?
Cheers...
Stephan
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://www.nabble.com/-asio--sync-receive_from-with-timeout-tp22326399p22332... Sent from the Boost - Users mailing list archive at Nabble.com.
Hi Michael,
while(!timeout.elapsed()) { boost::system::error_code ec; boost::asio::socket_base::non_blocking_io command(true); socket.io_control(command); bytesRead = _socket->read_some(boost::asio::buffer(data, dataBufferSize), ec);
if(error&&boost::asio::error::would_block!=error) { //there is some other error the client has disconnected; } else { //I must have got some data or theres no data yet check bytesRead for that } boost::this_thread::sleep( boost::posix_time::milliseconds(100)); } No extra threads necessary.
Indeed. But the way I see it, you gotta be aware that each of you reads will take at least 100 mils, right? In my scenario this is not really affordable. Or am I missing something here? The first read will never have something ready in a reliable way, right? Nice try though... Stephan
Perhaps... that was a bit over simplified as follows is better: while(!timeout.elapsed()) { boost::system::error_code ec; boost::asio::socket_base::non_blocking_io command(true); socket.io_control(command); bytesRead = _socket->read_some(boost::asio::buffer(data, dataBufferSize), ec); if(error&&boost::asio::error::would_block!=error) { //there is some other error the client has disconnected; } else if bytes read>0) { //I have some data _myDataDelegate.processData(data,bytesRead); } else { //No data for now lets take a break boost::this_thread::sleep( boost::posix_time::milliseconds(_myReadInterval)); } } Stephan Menzel-3 wrote:
Hi Michael,
while(!timeout.elapsed()) { boost::system::error_code ec; boost::asio::socket_base::non_blocking_io command(true); socket.io_control(command); bytesRead = _socket->read_some(boost::asio::buffer(data, dataBufferSize), ec);
if(error&&boost::asio::error::would_block!=error) { //there is some other error the client has disconnected; } else { //I must have got some data or theres no data yet check bytesRead for that } boost::this_thread::sleep( boost::posix_time::milliseconds(100)); } No extra threads necessary.
Indeed. But the way I see it, you gotta be aware that each of you reads will take at least 100 mils, right? In my scenario this is not really affordable.
Or am I missing something here? The first read will never have something ready in a reliable way, right? Nice try though...
Stephan
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://www.nabble.com/-asio--sync-receive_from-with-timeout-tp22326399p23451... Sent from the Boost - Users mailing list archive at Nabble.com.
mm.. people.. don't you think it's a bit expensive to start-interrupt threads during each sync read-write? am I missing something?
participants (3)
-
Michael Dehmlow
-
Roman Shmelev
-
Stephan Menzel