如何使用boost :: asio :: async_read_until和外部存储器地址作为缓冲区

时间:2011-10-07 15:53:32

标签: boost boost-asio asyncsocket

async_read_until要求basic_streambuf将数据读入其中。我不想分配额外的内存,而是使用内存地址(来自我不允许更改的指定接口)作为目标缓冲区。

是否可以使用外部内存地址创建streambuf,还是需要编写包装类?

1 个答案:

答案 0 :(得分:1)

最后通过编写我自己的async_read_until_delim类来解决这个问题,该类需要读取内存指针和最大字节值。它与原始的boost实现尽可能接近,但有一些调整可以带来更高性能的执行。

namespace {

template<typename read_handler>
class async_read_until_delim
{
public:
    async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
        char delim, read_handler& handler)
            : m_socket(socket), m_cur(static_cast<char*>(buffer)),
              m_end(static_cast<char*>(buffer) + max_read_size_in_bytes), m_delim(delim),
              m_handler(handler), m_pos(0)
        {
            read_some();
        }
    async_read_until_delim(async_read_until_delim const& other)
        : m_socket(other.m_socket), m_cur(other.m_cur), m_end(other.m_end), m_delim(other.m_delim),
          m_handler(other.m_handler), m_pos(other.m_pos)
        {
        }

    void operator()(boost::system::error_code const& error, std::size_t bytes_transferred)
        {
            if (!error)
            {    
                if (std::find(m_cur, m_end, m_delim) != m_end)
                {
                    m_handler(error, m_pos + bytes_transferred);
                    return;
                }
                else if (m_cur == m_end)
                {
                    m_handler(boost::asio::error::not_found, -1);
                    return;
                }

                m_cur += bytes_transferred;
                m_pos += bytes_transferred;

                read_some();
            }
            else
                m_handler(error, m_pos);
        }

private:
    void read_some()
        {
            m_socket.async_read_some(
                boost::asio::buffer(m_cur, m_end - m_cur), async_read_until_delim(*this));
        }

    tcp::socket&  m_socket;
    char         *m_cur,
                 *m_end;
    char          m_delim;
    read_handler  m_handler;
    std::size_t   m_pos;
};

template<typename read_handler>
inline void do_async_read_until_delim(tcp::socket& socket, void* buffer, std::size_t max_read_size_in_bytes,
    char delim, read_handler& handler)
{
    async_read_until_delim<read_handler>(socket, buffer, max_read_size_in_bytes, delim, handler);
}

} /* anonymous namespace */

所以,我希望它对某些人也有用。