Boost logo

Boost Users :

Subject: Re: [Boost-users] Using boost::asio::async_write to stream out data
From: Michael Caisse (boost_at_[hidden])
Date: 2009-07-17 20:18:44


Alex Black wrote:
> So, If I'm calling aysnc_write from the same thread each time, and I'm
> not waiting for previous writes to complete before starting a new
> write, how do I know when to free my buffer?
>
> The problem seems to be that the handle_write method will be called to
> let me know when the write is complete, but I won't have any
> information in handle_write to know *which* buffer to free... any
> suggestions?
>
> thx
>
> - Alex

Alex -

I recommend that you take a look at the asio chat example:

http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/examples.html#boost_asio.examples.chat

It has all kinds of little techniques to learn from.

Just to be clear on the "threads" reading/writing... I don't think you have "write thread"
and a "read thread". Typically you have a thread (or thread pool) that is working on
events. That thread (thread pool) calls io_service::run. There is some async read/write
that is initiated often from a different thread, but once stuff starts going your
completion routines (called from the io_service::run thread or pool) keeps things
going.

Typically you have some queue (like a std::deque) of input/output buffers to be
processed. You will see a messages to send deque in the chat
example.

Calling async_write multiple times for a single socket without controlling
completion would be considered "bad practice".

        // bad practice. wont allow your server to scale
        async_write( socket_, some_buffer1, some_completion_routine );
        async_write( socket_, some_buffer2, some_completion_routine );

Instead, you should queue items to be written and then utilize the completion routine
to start another async_write if there is something in the queue. Just like in the examples.
Just to be clear, a socket has a message queue.

The queue would be pop'd in the completion routine which would allow you to
handle which buffer to free. Ideally you just use RAII and let the problem be
solved for you automagically.

If you still want to go the route of willy-nilly calling async_write, you can
also get your buffer at the completion routine by changing the completion routine's
signature and using boost::bind. Something like this:

     async_write( socket_, asio_buffer,
                  bind( &write_done, shared_from_this(), raw_buffer, placeholders::error ) );

    void write_done( char* buffer, const error_code* error )
    {
         ....
         delete[] buffer; // or whatever it is
    }

I hope this helps some.

michael

-- 
----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com

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