| Home | Libraries | People | FAQ | More

##### basic_socket_streambuf::native_non_blocking (3 of 3 overloads)

Inherited from basic_socket.

Sets the non-blocking mode of the native socket implementation.

    boost::system::error_code native_non_blocking(
        bool mode,
        boost::system::error_code & ec);

This function is used to modify the non-blocking mode of the underlying native socket. It has no effect on the behaviour of the socket object's synchronous operations.

###### Parameters

mode

  If `true`, the underlying socket is put into non-blocking mode and direct system calls may fail with `boost::asio::error::would_block` (or the equivalent system error).

ec

  Set to indicate what error occurred, if any. If the `mode` is `false`, but the current value of `non_blocking()` is `true`, this function fails with `boost::asio::error::invalid_argument`, as the combination does not make sense.

###### Example

This function is intended to allow the encapsulation of arbitrary non-blocking system calls as asynchronous operations, in a way that is transparent to the user of the socket object. The following example illustrates how Linux's `sendfile` system call might be encapsulated:

    template <typename Handler>
    struct sendfile_op
    {
      tcp::socket& sock_;
      int fd_;
      Handler handler_;
      off_t offset_;
      std::size_t total_bytes_transferred_;

      // Function call operator meeting WriteHandler requirements.
      // Used as the handler for the async_write_some operation.
      void operator()(boost::system::error_code ec, std::size_t)
      {
        // Put the underlying socket into non-blocking mode.
        if (!ec)
          if (!sock_.native_non_blocking())
            sock_.native_non_blocking(true, ec);

        if (!ec)
        {
          for (;;)
          {
            // Try the system call.
            errno = 0;
            int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
            ec = boost::system::error_code(n < 0 ? errno : 0,
                boost::asio::error::get_system_category());
            total_bytes_transferred_ += ec ? 0 : n;

            // Retry operation immediately if interrupted by signal.
            if (ec == boost::asio::error::interrupted)
              continue;

            // Check if we need to run the operation again.
            if (ec == boost::asio::error::would_block
                || ec == boost::asio::error::try_again)
            {
              // We have to wait for the socket to become ready again.
              sock_.async_write_some(boost::asio::null_buffers(), *this);
              return;
            }

            if (ec || n == 0)
            {
              // An error occurred, or we have reached the end of the file.
              // Either way we must exit the loop so we can call the handler.
              break;
            }

            // Loop around to try calling sendfile again.
          }
        }

        // Pass result back to user's handler.
        handler_(ec, total_bytes_transferred_);
      }
    };

    template <typename Handler>
    void async_sendfile(tcp::socket& sock, int fd, Handler h)
    {
      sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
      sock.async_write_some(boost::asio::null_buffers(), op);
    }