как использовать boost :: asio :: async_read_until с адресом внешней памяти в качестве буфера - PullRequest
1 голос
/ 07 октября 2011

async_read_until ожидает basic_streambuf, в который будут считываться данные. Я не хочу выделять дополнительную память, но использую адрес памяти (из указанного интерфейса, который мне нельзя изменять) в качестве целевого буфера.

Можно ли создать streambuf с адресом внешней памяти или мне нужно написать класс-оболочку?

1 Ответ

1 голос
/ 10 октября 2011

Наконец решил проблему, написав свой собственный класс 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 */

Так что, я надеюсь, это будет полезно и для кого-то.

...