Boost logo

Boost Users :

Subject: Re: [Boost-users] [boost-users][asio] async operations order.
From: Matheus Araújo Aguiar (matheus.pit_at_[hidden])
Date: 2009-12-16 06:49:01


Hello,

On Tue, Dec 15, 2009 at 7:23 PM, Germán Diago <germandiago_at_[hidden]> wrote:

> Hello. I'm implementing a fully asynchronous server and I would like to
> know
> the order of async operations.
>
> The server receives, first of all, a size, and later the data.
>
> The onSizeRead handler allocates the memory required to store the data
> that is coming after
> the async_read.
> So I would like to know if this buffer will be available when
> onDataRead is called.
>

You have to guarantee that by allocating the buffer on the heap, by using a
object that it is not on the local scope of your async call, or by using
other methods. The important thing is to ensure the buffer will be alive
between the call to the async operation and the call to the async operation
handler.

>
> so I get the size and data with two async_read operations.
>
> I would like to know if the relative order of the async calls is
> respected, since I'm
> reading from the same socket for both operations and I need the
> resources dictated by the first read
> before using the second one.
>

The relative order of the async calls is respected if you actively ensure
that. If you request a size_read and data_read, both async, one after
another without waiting for the first to complete, then there is no
guarantee that they will be performed in the right order... to do that one
could write something like this:

/* Reads the size of the incoming data */
void TCP_connection::read_header()
{
    unsigned char* header = new unsigned char[header_size]; //header_size
is a const defined by your application, you could use for example
sizeof(unsigned short)

    boost::asio::async_read(socket, boost::asio::buffer(header,
header_size),
                            boost::bind(&TCP_connection::OnSizeRead, this,
                            boost::asio::placeholders::error,
                            header,
boost::asio::placeholders::bytes_transferred));
}
/* Starts the data receive */
void TCP_connection::onSizeRead(const boost::system::error_code& error,
const unsigned char* header, std::size_t bytes)
{
    if(!error)
    {
        unsigned short message_length;
        memcpy(&message_lenght, header, sizeof(header_size));

        if(message_lenght > 0)
        {
unsigned char* data = new unsigned char[message_length];
boost::asio::async_read(socket, boost::asio::buffer(data, message_length),
                     boost::bind(&TCP_connection::onDataRead, this,
                     boost::asio::placeholders::error,
                     data, boost::asio::placeholders::bytes_transferred));
         }
    }
    delete[ ] header;
}

 This ensures that the size of the data is always read first. Also, note
that in this example i use buffer allocation with the operator new(). You
might want to use buffers already allocated and then instead of deleting
them, just set them free to reuse. The only requirement is that you have
enough space to accomodate the data and that the buffer will outlive the
call to the async operation.

Hope it helps,

> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>

-- 
Matheus Araújo Aguiar
Computer Scientist
matheus.pit_at_[hidden]


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net