Boost logo

Boost Users :

Subject: Re: [Boost-users] [asio] user defined composed operations and strands
From: Marat Abrarov (abrarov_at_[hidden])
Date: 2011-08-09 16:08:45


Hi, Tacheon.

> If async_write_data is called and io_service::run is called from multiple threads, strands are should
> be necessary to avoid raced.
> The question is: How do I support handlers wrapped in a strand and how do I get this strand forwarded
> to async_read?
> As far as I understand this should be somehow possible by using asio_handler_invoke but the
> documentation is a bit too fuzzy on the topic for me to understand.

There is no such info in Asio docs.
 
You may look at asio-samples (http://sourceforge.net/projects/asio-samples). There is ma::context_wrapped_handler class
(and ma::make_context_wrapped_handler helper function) that makes such a wrapper for intermediate handler. But you
shouldn't use

> typedef boost::function<void (error_t const &)> completion_handler_t;

because it hides asio_hanlder_invoke defined for the original (user supplied) handler.

You may write something like this:
 
class io_port
{
public:
     //Ctors and so on...

    template<typename Handler>
    void async_read_data
        ( raw_buffer_t & buffer
        , Handler const & handler)
    {
         //uses a composed operation itself...
        boost::asio::async_read
             ( socket
             , boost::asio::buffer(header)
             , ma::make_context_wrapped_handler(handler,
                   boost::bind
                     ( &io_port::handle_header_received<Handler>
                     , this
                     , boost::ref(buffer)
                     , handler
                     , boost::asio::placeholders::error)));
    }

    //first intermediate handler
    template<typename Handler>
    void handle_header_received
        ( raw_buffer_t & data
        , Handler const & handler
        , boost::system::error_code const & error
    {
        if(error)
        {
            handler(error_t(error));
        }
        else
        {
            prepare_buffer(data, header.perparation_data()); //pseudo-code
            //uses a composed operation itself...
            boost::asio::async_read
                ( socket
                , boost::asio::buffer(data)
                , ma::make_context_wrapped_handler(handler,
                   boost::bind(&io_port::handle_data_received<Handler>
                    , this
                    , boost::ref(buffer)
                    , handler
                    , boost::asio::placeholders::error) );
        }
    }

    //second intermediate handler
    template<typename Handler>
    void handle_data_received
        ( raw_buffer_t & data
        , Handler const & handler
        , boost::system::error_code const & error )
    {
        if(error)
        {
            handler(error_t(error));
        }
        else
        {
            handler(error_t());
        }
    }

};

Also, it will be very helpful to read Asio sources: /boost/asio/impl/read.hpp: 339 and 145 (Boost 1.47).
May be it' will be better to implement io_port class similar to boost::asio::detail::read_op.

Regards,
Marat Abrarov.


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