Menu

#19 support for MSG_DONTWAIT to save a few system calls

open
nobody
None
5
2014-08-19
2012-09-04
bastiaan
No

We have a use case with a tcp connection pool, where we want to do a quick check if a connection is still valid before re-using it.

We currently basically do it as follows (using the boost version of asio):

boost::asio::ip::tcp::socket & s = get_socket();
s.non_blocking(true);
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), s.message_peek);
s.non_blocking(false);

This nicely reports a connection that was closed by the peer, in which case we can reconnect. However, it uses a number of additional system calls to set the socket to non-blocking and back to blocking that could be eliminated on Linux, and maybe also on other OSes.

Linux supports MSG_DONTWAIT. It would be nice if asio could also support this flag, if it is available. Then we could do:

boost::asio::ip::tcp::socket & s = get_socket();
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), s.message_dontwait | s.message_peek);

This would eliminate the system calls to set the socket to blocking / non-blocking.

We have tried:

boost::asio::ip::tcp::socket & s = get_socket();
char buf[1];
s.receive(boost::asio::buffer(buf, sizeof(buf)), MSG_DONTWAIT | s.message_peek);

This however blocks the program. For example, the above code goes down to socket_ops::sync_recv, which has:

// Operation failed.
if ((state & user_set_non_blocking)
|| (ec != boost::asio::error::would_block
&& ec != boost::asio::error::try_again))
return 0;

But for MSG_DONTWAIT to work, sync_recv would need:

// Operation failed.
if ((state & user_set_non_blocking)
|| (flags & MSG_DONTWAIT)
|| (ec != boost::asio::error::would_block
&& ec != boost::asio::error::try_again))
return 0;

With this patch, the receive call with MSG_DONTWAIT works as expected. In socket_ops.ipp, more functions similar to sync_recv could add support MSG_DONTWAIT in this way.

It would be nice to be able to use MSG_DONTWAIT with the asio API. If necessary we can go more low-level through s.native_handle().

Discussion


Log in to post a comment.