1

Is it possible to use Boost's asio to do non-blocking IO without using async callbacks? I.e. equivalent to the O_NONBLOCK socket option.

I basically want this function:

template<typename SyncWriteStream,
         typename ConstBufferSequence>
std::size_t write_nonblock(
    SyncWriteStream & s,
    const ConstBufferSequence & buffers);

This function will write as many bytes as it can and return immediately. It may write 0 bytes.

Is it possible?

Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • *How* could it "return" the number of bytes written if it returns immediately? How would you be able to tell if the data has been sent or not? If there are errors? It's not possible without some kind of callbacks. – Some programmer dude Feb 02 '16 at 10:36
  • It would write them to an internal buffer. Take a look at `O_NONBLOCK`. – Timmmm Feb 02 '16 at 16:03
  • I know about non-blocking sockets, I wonder how you would tell the program that the `write` call succeeded or failed if you don't want to use callbacks. And how would you even *know* when the `write` function was finished without some kind of polling? Will you do that in the main program? Poll some status buffer? Asynchronous programming isn't just as simple as "call non-blocking function and then continue my merry way". – Some programmer dude Feb 02 '16 at 17:28
  • A later call would fail. Simple. – Timmmm Feb 03 '16 at 08:02

2 Answers2

3

Yes, using the non_blocking() method to put the socket into Asio non-blocking mode:

template<typename SyncWriteStream,
         typename ConstBufferSequence>
std::size_t write_nonblock(
    SyncWriteStream & s,
    const ConstBufferSequence & buffers)
{
    s.non_blocking(true);
    boost::system::error_code ec;
    auto bytes = s.send(buffers, 0, ec);
    if (bytes == 0 && !(ec == boost::asio::error::would_block))
        throw boost::system::system_error(ec, "write_nonblock send");
    return bytes;
}
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • can I do the same thing while doing a read ? Should I have to set `s.non_blocking(true)` before every socket read or write call ? – TheWaterProgrammer Feb 01 '17 at 13:04
  • 1
    @SegmentationFault yes, you can use the `receive` member function to perform a single read. The `non_blocking` property persists between calls, so you don't have to re-issue `s.non_blocking(true)` each time. – ecatmur Feb 01 '17 at 17:24
-1

The way with s.non_blocking(true) would not work. If you check send implementation, it uses socket_ops::sync_send, which does poll_write if send failed.

So it is still blocking on top level.