Stephan,

I had to program smth similar. Than a tried some "non-standard" approach. If you use boost threads to handle socket communication, when the socket is blocked you can interrupt the thread which owns the socket. You will receive the interruption exception and handle your socket cancel there. This is not documentation conform in so far, since boost::thread doc states, that you might only cancel threads which are in an interruption point or will enter it. Asio or Boost::Threads simply ignore each other and nowhere in the docs of asio is stated smth about boost::threads, but as it seems asio socket when it waits for input is in such an interruption point (may be it uses boost::threads internally) and therefore can be interrupted, but that's not documented. I tested this with gcc compiler and it worked. May be this would be a possible fix for asio developers to promise that synchronous sockets are interruptable via boost::thread interruption.

Actually in my case it was a prototype, and it stayed so and I probably would never rely on that in the production code, but wanted to show that there might be a quick fix for this issue.


Best Regards,
Ovanes

On Wed, Mar 4, 2009 at 10:23 AM, Stephan Menzel <stephan.menzel@gmx.eu> 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::optional<boost::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::optional<boost::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::optional<boost::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