Menu

#4 Documentation error: async_write() "always returns immediately" [false?]

v1.0 (example)
open
nobody
None
5
2015-02-20
2014-04-03
sfuser3
No

The program shown below was compiled using GNU g++ v4.4.3:

$ g++ -o main main.cc -lboost_system  # Boost 1-55-0

The program prints the string
@The quick brown fox jumps over the lazy dog.
one character at a time and, in doing so, it clearly demonstrates that both:

  • a call to the CompletionCheck functor occurs, and
  • the output of the first character [i.e. @] occurs

before the call to async_write() returns. The evidence can be found on the 1st and 2nd lines of the program's output:

$ ./main
 - CompletionCheck::operator()(error=system:0, bytes transferred=0)
@ - async_write() has returned
The quick brown fox jumps over the lazy dog.
handler() - completion handler called

which shows:

  • 1st line: The functor output [e.g. "bytes_transferred=0"]
  • 2nd line: The string's first character, the "@" symbol, followed by
  • 2nd line: The text: " - async_write() has returned".

The rest of the string is printed only after invoking the io_service's run() method.

So: Is the async_write() documentation incorrect when it states that the call "always returns immediately" ?

I would have expected nothing to happen until calling the run() method.


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <vector>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

static void handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    std::cerr << "handler() - completion handler called" << std::endl;
}

class CompletionCheck
{
public:
    CompletionCheck(std::vector<boost::asio::const_buffer>& buffers)
    :   count_(boost::asio::buffer_size(buffers))
    {
    }

    size_t operator()(const boost::system::error_code& error, std::size_t bytes_transferred)
    {
        if (bytes_transferred == 0)
        {
            std::cerr << " - CompletionCheck::operator()(error=" << error
                      << ", bytes transferred=" << bytes_transferred << ")" << std::endl;
        }

        if (count_)
        {
            --count_;
            return 1;
        }
        return 0;
    }

private:
    size_t  count_;
};

int main(int argc, char * argv[])
{
    boost::asio::io_service iosvc;

    std::vector<boost::asio::const_buffer> vec;
    vec.push_back(boost::asio::buffer("@The"));
    vec.push_back(boost::asio::buffer(" quick"));
    vec.push_back(boost::asio::buffer(" brown"));
    vec.push_back(boost::asio::buffer(" fox"));
    vec.push_back(boost::asio::buffer(" jumps"));
    vec.push_back(boost::asio::buffer(" over"));
    vec.push_back(boost::asio::buffer(" the"));
    vec.push_back(boost::asio::buffer(" lazy"));
    vec.push_back(boost::asio::buffer(" dog.\n"));

    boost::asio::posix::stream_descriptor ios(iosvc);
    ios.assign(::open("/dev/tty", O_WRONLY|O_ASYNC));
    CompletionCheck check(vec);

    boost::asio::async_write(ios, vec, check, boost::bind(&handler, _1, _2));
    std::cerr << " - async_write() has returned" << std::endl;

    iosvc.run();

    return 0;
}

Discussion


Log in to post a comment.